【问题标题】:MVVM-Light and WPF User control libraryMVVM-Light 和 WPF 用户控件库
【发布时间】:2019-01-13 03:09:33
【问题描述】:

我必须在独立的用户控件库中创建一个 WPF 用户控件。 我想使用 MVVM-light。 问题,SimpleIOC 通常设置在主应用程序中,并通过 app.xaml 作为资源添加到主应用程序。

如何最好地解决它,以便引用的用户控件库可以访问 SimpleIOC 容器? 在哪里注册用户控件的 ViewModel 最好?

我发现以下线程似乎是同一个问题,但答案帖子中提供的链接中不再有任何关于解决方案的信息。 How can MVVM Light be used in a WPF User Control Library project?

【问题讨论】:

    标签: wpf mvvm user-controls mvvm-light


    【解决方案1】:

    如果独立类库中的视图依赖于视图模型定位器,而视图模型定位器又依赖于视图模型类,则可以将 ViewModelLocator 类定义为视图模型项目中的单例并引用此项目来自用户控件库和 WPF 应用程序本身:

    ViewModels/ViewModelLocator.cs:

    public sealed class ViewModelLocator
    {
        private static readonly ViewModelLocator _instance = new ViewModelLocator();
    
        private ViewModelLocator()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
            SimpleIoc.Default.Register<MainViewModel>();
        }
    
        public static ViewModelLocator Instance => _instance;
    
        public MainViewModel Main
        {
            get
            {
                return ServiceLocator.Current.GetInstance<MainViewModel>();
            }
        }
    }
    

    视图/UserControl1.xaml:

    <UserControl x:Class="Views.UserControl1"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:viewModels="clr-namespace:ViewModels;assembly=ViewModels"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300"
                 DataContext="{Binding Main, Source={x:Static viewModels:ViewModelLocator.Instance}}">
        <Grid>
    
        </Grid>
    </UserControl>
    

    WpfApp4/MainWindow.xaml:

    <Window x:Class="WpfApp4.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:views="clr-namespace:Views;assembly=Views"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <views:UserControl1 />
        </Grid>
    </Window>
    

    【讨论】:

    • 谢谢,这或多或少是我想要的。在我的例子中,MainViewModel 将位于 WpfApp4 中,而 UserControl 将在 Views 项目中拥有其 UserControlViewModel。目前 ViewModelLocator 也在 WpfApp4 项目中,但我认为没有理由不能将它移到单独的项目中。这里解释的概念当然是我想要的。谢谢
    【解决方案2】:

    目前还不清楚您遇到了问题的哪一部分。您库中的视图模型可以像任何其他视图模型一样注册:

    SimpleIoc.Default.Register<MainViewModel>();
    SimpleIoc.Default.Register<YourClassLibrary.YourClassLibViewModel>();
    ... etc ...
    

    如果您的类库有需要包含在主应用程序资源字典中的对象(即 DataTemplates 等),那么就像您通常在 App.xaml 中所做的那样将它们放入 ResourceDictionary...。

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:YourClassLibrary">
    
        <DataTemplate DataType="{x:Type local:YourClassLibViewModel}">
            <local:YourClassLibUserControl />
        </DataTemplate>
    
    </ResourceDictionary>
    

    ...然后将其添加到主应用程序的 ResourceDictionary 的 MergedDictionaries 列表中:

    <Application.Resources>
        <ResourceDictionary>
    
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/YourClasssLibrary;component/YourResourceDictionary.xaml" />
            </ResourceDictionary.MergedDictionaries>
    
            <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:YourMainApp.ViewModel" />
    
        </ResourceDictionary>
    </Application.Resources>
    

    【讨论】:

    • 谢谢,如果我不清楚,很抱歉(对 WPF 没有太多经验)。所以请耐心等待。如果我创建一个 MVVM 轻应用程序,我在 MainApplication 中有一个 ViewModelLocator,它包含一个 SimpleIOC。在我的情况下,我在同一个解决方案中的一个单独的用户控件库项目中也有一个用户控件。稍后我将放置在主应用程序中的用户控件。但是我需要以某种方式使该用户控件了解 SimpleIOC 或使用其自己的 SimpleIOC 定位器,将其 VM 注册到它并在视图中绑定到定位器中的 VM 实例。如何在用户控件库中做到这一点?
    • 我只是创建一个你的控件库的实例(例如MyClassModule)并给它一个接受ISimpleIoc类型的函数并为你的每个视图模型调用ISimpleIoc.Register()。然后回到你的视图定位器让它调用那个函数,传递一个对自身的引用,即new MyClassModule().RegisterViewModels(this)
    • 我已经尝试过了,但我的问题是在设计时 VM 在 XAML 编辑器中不可用,因此我无法选择绑定到 VM 属性。
    • 似乎可行的是在本地 ResourceDictionary 的用户控件库中创建一个新的 ViewModelLocator,并在用户控件内使用其 Ioc 容器。但这意味着 MainApplication 和 User 控件不共享同一个 Ioc 容器。
    • 我没有关注......你是什么意思他们“在 XAML 编辑器中不可用”?只要您正确声明命名空间,它就可以正常工作。唯一真正的区别是命名空间声明还必须指定程序集,例如xmlns:libvms="clr-namespace:YourProject.ViewModels;assembly=YourProject"。然后,您只需在 XAML 中将它们指定为 libvms:YourViewModel
    猜你喜欢
    • 1970-01-01
    • 2011-03-21
    • 1970-01-01
    • 1970-01-01
    • 2011-03-07
    • 2014-12-03
    • 1970-01-01
    • 2012-07-08
    • 2017-01-21
    相关资源
    最近更新 更多