精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
锐英源精品原创,禁止全文或局部转载,禁止任何形式的非法使用,侵权必究。点名“简易百科”和闲暇巴盗用锐英源原创内容。
WPF的MVVM中的ViewModel负责View的数据组织,一般是一个View对应一个ViewModel,但是如果能灵活自动定位,就会能解决一些奇怪的问题,比如通用的View对应多个ViewModel,所以有兴趣的朋友请认真看本篇翻译。
提示下:看不懂codeproject,找锐英源。
ViewModels我将在 MVVM 模式的实例化中介绍一个小技巧。
有时,我们在 WPF 小型解决方案中工作,其中通常不需要ViewModelLocator类作为ViewModels类生成器,因为我们不需要保存ViewModels引用。我们不会担心为ViewModelLocator类提供食物,我们将立即部署我们的ViewModels类。这与单元测试和绑定引擎完美契合。
我们会有两种情况:
在这种情况下,只需在视图中配置一个属性:
<Window x:Class="AutoMVVMLocator.Example1View"
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:local="clr-namespace:AutoMVVMLocator"
local:MLMVVM.IsAutomaticLocator="True"
mc:Ignorable="d"
Title="Example1View" Height="300" Width="300">
重要的部分是:
local:MLMVVM.IsAutomaticLocator = "True"
在这个例子中,视图Example1View自动实例化一个Example1ViewModel作为DataContext对象。
在这种情况下,我们需要指定另一个具有ViewModel类名称的属性。
<Window x:Class="AutoMVVMLocator.Example2Window"
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:local="clr-namespace:AutoMVVMLocator"
local:MLMVVM.ViewModelClassName="Example2ViewModel"
local:MLMVVM.IsAutomaticLocator="True"
mc:Ignorable="d"
Title="Example2Window" Height="300" Width="396.546">
重要的部分:
local:MLMVVM.ViewModelClassName = "Example2ViewModel" local:MLMVVM.IsAutomaticLocator = "True"
注意:属性ViewModelClassName必须放在首位。
在这个例子中,视图Example2Window自动实例化一个Example2ViewModel作为DataContext对象。
这是一个非常简单的类。它有两种AtachProperties和两种private方法。
这些attachproperties是以前配置的属性:
public static bool GetIsAutomaticLocator(DependencyObject obj)
{
return (bool)obj.GetValue(IsAutomaticLocatorProperty);
}
public static void SetIsAutomaticLocator(DependencyObject obj, bool value)
{
obj.SetValue(IsAutomaticLocatorProperty, value);
}
public static readonly DependencyProperty IsAutomaticLocatorProperty =
DependencyProperty.RegisterAttached("IsAutomaticLocator",
typeof(bool), typeof(MLMVVM), new PropertyMetadata(false, IsAutomaticLocatorChanged));
private static void IsAutomaticLocatorChanged
(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var callOwner = d as FrameworkElement;
var className = GetViewModelClassName(d);
var userControl = GetInstanceOf(callOwner.GetType(), className);
callOwner.DataContext = userControl;
}
public static string GetViewModelClassName(DependencyObject obj)
{
return (string)obj.GetValue(ViewModelClassNameProperty);
}
public static void SetViewModelClassName(DependencyObject obj, string value)
{
obj.SetValue(ViewModelClassNameProperty, value);
}
public static readonly DependencyProperty ViewModelClassNameProperty =
DependencyProperty.RegisterAttached("ViewModelClassName",
typeof(string), typeof(MLMVVM), new PropertyMetadata(null));
这两个private方法包含一个动态实例引擎:
private static object GetInstanceOf(Type dependencyPropertyType, string className)
{
var assembly = dependencyPropertyType.Assembly;
var assemblyTypes = assembly.GetTypes();
var classNameDef = GetClassName(dependencyPropertyType, className);
var userControlType = assemblyTypes.FirstOrDefault(a => a.Name.Contains(classNameDef));
if (userControlType == null)
throw new ArgumentException($"Not exist a type
{classNameDef} in the assembly {assembly.FullName}");
var resultado = Activator.CreateInstance(userControlType);
return resultado;
}
private static string GetClassName(Type dependencyPropertyType, string className)
{
if (string.IsNullOrWhiteSpace(className))
return $"{dependencyPropertyType.Name}Model";
return className;
}
如果你在做一个伟大的项目,或者你需要恢复ViewModels实例的引用,你必须使用一个经典的ViewModelLocator类。
注:作者其实扩展了框架,用了DependencyObject,这些框架功能在常见的mvvm框架里都有,但本文对于学习框架有价值。