本文介绍了如何在用户控件中使用ViewModelLocator?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I was asked to convert a standalone WPF application that uses the MVVM pattern into a user control. This app consists of a main window and a few other windows. However, I get a few errors when trying to do so all pointing to my App.xaml class and other resources declared like converters:

Library project file cannot specify ApplicationDefintion element.The project file contains a property value that is not valid.The name "ViewModelLocator" does not exist in the namespace "clr-namespace:MapperX.ViewModels".

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

So it looks like the errors revolve around my ViewModelLocator.

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

Currently the project directory structure is set up like so:

顶级-> ViewModels文件夹-> ViewModelLocator

Top level -> ViewModels folder -> ViewModelLocator

App.xaml的设置如下:

The App.xaml is set up like so:

<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类的代码段:

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;
            }
        }
    }
}

然后为视图.xaml设置DataContext,如下所示:DataContext="{Binding Path=MainViewModel, Source={StaticResource ViewModelLocator}}"

And then I set the DataContext for the views .xaml like so:DataContext="{Binding Path=MainViewModel, Source={StaticResource ViewModelLocator}}"

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

What's the correct way to still be able to use the ViewModelLocator without the App.xaml??

推荐答案

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

Instead of relying on a resource, you may create an attached property to set the DataContext of the views in your control library:

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">

这篇关于如何在用户控件中使用ViewModelLocator?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 00:23