如何在用户控件中使用ViewModelLocator?

时间:2019-01-10 13:26:11

标签: c# wpf user-controls app.xaml viewmodellocator

有人要求我将使用MVVM模式的独立WPF应用程序转换为用户控件。这个应用程序包含一个主窗口和一些其他窗口。但是,尝试这样做时会遇到一些错误,它们都指向我的App.xaml类和声明为转换器的其他资源:

/dev/ttyACM0 Library project file cannot specify ApplicationDefintion element. The project file contains a property value that is not valid.

所以看起来错误围绕着我的ViewModelLocator。

当前,项目目录结构的设置如下:

顶级-> ViewModels文件夹-> ViewModelLocator

App.xaml的设置如下:

The name "ViewModelLocator" does not exist in the namespace "clr-namespace:MapperX.ViewModels"

这是<Application x:Class="MapperX.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:MapperX" xmlns:vm="clr-namespace:MapperX.ViewModels" StartupUri="MainWindow.xaml"> <Application.Resources> <vm:ViewModelLocator x:Key="ViewModelLocator" /> </Application.Resources> </Application> 类的摘要:

ViewModelLocator

然后,我为视图.xaml设置namespace MapperX.ViewModels { /// <summary> /// This class instantiates all the viewmodels /// </summary> public class ViewModelLocator { WpfMap map = new WpfMap(); private MainViewModel _mainViewModel; public MainViewModel MainViewModel { get { if (_mainViewModel == null) { _mainViewModel = new MainViewModel(map) } return _mainViewModel; } } private LayersViewModel _layersViewModel; public LayersViewModel LayersViewModel { get { if (_layersViewModel == null) { _layersViewModel = new LayersViewModel(map) } return _layersViewModel; } } } } ,如下所示: DataContext

在没有App.xaml的情况下仍然能够使用ViewModelLocator的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

为什么不将ViewModelLocator放在顶层UserControl中?

<UserControl.Resources>
   <vm:ViewModelLocator x:Key="ViewModelLocator" />
</UserControl.Resources>

答案 1 :(得分:1)

您可以创建一个附加属性来设置控件库中视图的DataContext,而不是依赖资源:

namespace ControlsAndResources
{
    public class View
    {
        private static readonly ViewModelLocator s_viewModelLocator = new ViewModelLocator();

        public static readonly DependencyProperty ViewModelProperty = DependencyProperty.RegisterAttached("ViewModel", typeof(string), 
            typeof(ViewModelLocator), new PropertyMetadata(new PropertyChangedCallback(OnChanged)));

        public static void SetViewModel(UserControl view, string value) => view.SetValue(ViewModelProperty, value);

        public static string GetViewModel(UserControl view) => (string)view.GetValue(ViewModelProperty);

        private static void OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            UserControl view = (UserControl)d;
            string viewModel = e.NewValue as string;
            switch (viewModel)
            {
                case "MainViewModel":
                    view.DataContext = s_viewModelLocator.MainViewModel;
                    break;
                case "LayersViewModel":
                    view.DataContext = s_viewModelLocator.LayersViewModel;
                    break;
                default:
                    view.DataContext = null;
                    break;
            }
        }
    }
}

用法:

<UserControl xmlns:local="clr-namespace:ControlsAndResources" ... 
             local:View.ViewModel="MainViewModel">