精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
锐英源精品原创,禁止全文或局部转载,禁止任何形式的非法使用,侵权必究。点名“简易百科”和闲暇巴盗用锐英源原创内容。
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框架里都有,但本文对于学习框架有价值。