假设我们有一个像这样的通用View模型:
public class MyViewModel<T> : INotifyPropertyChanged where T : Class1
{
private T _objectModel;
public MyViewModel(T object)
{
_objectModel= object;
}
public event PropertyChangedEventHandler PropertyChanged;
}
当我想将此视图模型绑定到DataContext
中UserControl
的{{1}}时,我不能! XAML编辑器找不到My View Model类。我应该如何在XAML中引用泛型类型?
XAML
在上面的代码中,<UserControl.DataContext>
<s:MyViewModel<T>/> // How should I write this here????
</UserControl.DataContext>
是我的工作区的别名,如果我将我的通用视图模型转换为具体的类,它可以正常工作。
答案 0 :(得分:6)
使用XAML时,无法在XAML代码中使用泛型参数实例化视图模型。
要解决此问题,您需要使用继承,这是一个示例:
public abstract class ViewModel<T>
用法:
public class MovieViewModel : ViewModel<Movie>
...
public class GenreViewModel : ViewModel<Genre>
为每个模型创建一个新类似乎有点愚蠢,但这根本不是真的。通过假设每个视图模型包含一个模型,您几乎已经为在所有视图模型中遵循此模式做好准备,因为您的基本视图模型强制执行此约束。
我个人使用ViewModel<T>
基类的模式,其中T
是模型。
将逻辑与基本视图模型分开当然是个好主意。事实上,每个模型的视图模型都是一个非常好的模式。
还有另一种方法可以实现您所追求的目标,这只是从视图模型库中删除泛型,请考虑以下示例:
public class ViewModel
{
public object Model { get; protected set; }
}
现在,如果您使用Model
填充Movie
,则XAML会将其视为Movie
,而不是object
。现在,就你的XAML方面而言,这是非常好的,但是,当你在 C#中开始使用这个模型时,你将会遇到各种各样的问题,因为你需要施放您正在使用的任何类型的对象。所以我根本不会推荐这个。
解决这个问题的另一种方法是在代码隐藏中设置DataContext
,如果你要这样做,那么,只有上帝现在可以救你。围绕MVVM设计模式的主要思想是View逻辑和业务层(View Models)的分离,一旦View开始实例化视图模型,那么很好的分离就会丢失。
现在这样说,没有什么可以阻止你做这件事,我之前已多次这样说了。 MVVM是一种设计模式,不是法律,如果你想在代码隐藏中设置DataContext
,那么公平,但重要的是你要意识到其含义。
答案 1 :(得分:4)
您可以创建一个继承自通用ViewModel并使用该
的类public class PersonViewModel : ViewModel<Person>
XAML:
<UserControl.DataContext>
<s:PersonViewModel/>
</UserControl.DataContext>
答案 2 :(得分:2)
您无法在XAML中设置通用视图模型,因为XAML在编译时需要已知类型。
依赖注入是你最好的选择
public class MyControl : UserControl{
public MyControl(Object viewModel){
this.DataContext = viewModel;
}
}
答案 3 :(得分:1)
如果您的ViewModel是从基类派生的,那么让我们说NonGenericViewModel然后您可以在代码中将NonGenericViewModel类型的对象分配给DataContext。使用这种方式你仍然可以获得泛型的好处,数据绑定也可以工作,因为绑定将在运行时进行,无论你分配给DataContext的对象是什么类型,只要它具有xaml所需的属性,集合等。控制。
BaseViewModel<T> : NonGenericViewModel { ... }
NonGenericViewModel : INotifyPropertyChanged { ... }
在后面的代码中,在你的xaml.cs的代码中:
NonGenericViewModel nonGenVM = new BaseViewModel<person>();
this.DataContext = nonGenVM;
即使这是正确的,也是有效的:
this.DataContext = new BaseViewModel<Person>();
这取决于你是否需要在其他地方使用NonGenericViewModel类。