如何在用户控件中使用 ViewModelLocator?
How to use a ViewModelLocator in a user control?
我被要求将使用 MVVM 模式的独立 WPF 应用程序转换为用户控件。这个应用程序由一个主要 window 和一些其他 windows 组成。但是,尝试这样做时我遇到了一些错误,所有错误都指向我的 App.xaml class 和声明为转换器的其他资源:
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 有关。
目前项目目录结构是这样设置的:
顶级 -> ViewModels 文件夹 -> ViewModelLocator
App.xaml设置如下:
<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
class 的片段:
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
。xaml 如下所示:
DataContext="{Binding Path=MainViewModel, Source={StaticResource ViewModelLocator}}"
在没有 App.xaml 的情况下仍能使用 ViewModelLocator 的正确方法是什么?
为什么不把 ViewModelLocator
放在你的顶级 UserControl
中?
<UserControl.Resources>
<vm:ViewModelLocator x:Key="ViewModelLocator" />
</UserControl.Resources>
您可以创建附加的 属性 来设置控件库中视图的 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">
我被要求将使用 MVVM 模式的独立 WPF 应用程序转换为用户控件。这个应用程序由一个主要 window 和一些其他 windows 组成。但是,尝试这样做时我遇到了一些错误,所有错误都指向我的 App.xaml class 和声明为转换器的其他资源:
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 有关。
目前项目目录结构是这样设置的:
顶级 -> ViewModels 文件夹 -> ViewModelLocator
App.xaml设置如下:
<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
class 的片段:
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
。xaml 如下所示:
DataContext="{Binding Path=MainViewModel, Source={StaticResource ViewModelLocator}}"
在没有 App.xaml 的情况下仍能使用 ViewModelLocator 的正确方法是什么?
为什么不把 ViewModelLocator
放在你的顶级 UserControl
中?
<UserControl.Resources>
<vm:ViewModelLocator x:Key="ViewModelLocator" />
</UserControl.Resources>
您可以创建附加的 属性 来设置控件库中视图的 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">