简体   繁体   English

如何将DataContext绑定到XAML中的通用ViewModel?

[英]How Can I bind DataContext to a Generic ViewModel in XAML?

Suppose we have a generic View model like this: 假设我们有一个像这样的通用View模型:

public class MyViewModel<T> : INotifyPropertyChanged where T : Class1
{
    private T _objectModel;
    public MyViewModel(T object)
    {
        _objectModel= object;
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

When I want to bind this View Model to DataContext of my UserControl in XAML , I can not! 当我想在XAML将此View Model绑定到UserControl DataContext时,我不能! XAML editor does not find My View Model class. XAML编辑器找不到My View Model类。 How should I refer to a generic type in XAML? 我应该如何在XAML中引用泛型类型?

<UserControl.DataContext>
    <s:MyViewModel<T>/> // How should I write this here????
</UserControl.DataContext> 

In the above code s is an alias for my workspace, and If I convert my generic View Model to a concrete class it works normally. 在上面的代码中, s是我的工作区的别名,如果我将我的通用视图模型转换为具体类,它可以正常工作。

When working with XAML, you cannot instantiate a view model with a generic parameter in XAML code. 使用XAML时,无法在XAML代码中使用泛型参数实例化视图模型。

To work around this, you need to make use of inheritance , here's an example: 要解决这个问题,你需要使用继承 ,这是一个例子:

public abstract class ViewModel<T>

Usage: 用法:

public class MovieViewModel : ViewModel<Movie>

...

public class GenreViewModel : ViewModel<Genre>

Creating a new class for each model seems to be a bit stupid, however this simply isn't true. 为每个模型创建一个新类似乎有点愚蠢,但这根本不是真的。 By making the assumption that each view model contains one model, you've pretty much set yourself up for following this pattern in all view models, as your base view model enforces this constraint. 通过假设每个视图模型包含一个模型,您几乎已经为在所有视图模型中遵循此模式做好准备,因为基本视图模型强制执行此约束。

I personally use the pattern of using a ViewModel<T> base class, where T is the model. 我个人使用ViewModel<T>基类的模式,其中T是模型。

It's certainly a good idea to keep the logic separated from your base view model. 保持逻辑与基本视图模型分离当然是个好主意。 A view model for each model is in fact a very good pattern to implement. 事实上,每个模型的视图模型都是一个非常好的模式。


There is another way you can achieve what you're after, this is simply removing the generic from the view model base, consider the example: 还有另一种方法可以实现您所追求的目标,这只是从视图模型库中删除泛型,请考虑以下示例:

public class ViewModel
{
    public object Model { get; protected set; }
}

Now, if you populate Model with let's say a Movie , then XAML will see it as a Movie , and not an object . 现在,如果你用一个Movie填充Model ,那么XAML会将它看作一个Movie ,而不是一个object Now this is pretty nifty as far as your XAML side goes, however, when you start working with this model in C# , then you're going to have all sorts of problems as you'll have to cast the object to whatever type you are using. 现在,就你的XAML方面而言,这是非常好的,但是,当你在C#中开始使用这个模型时,你会遇到各种各样的问题,因为你必须将对象转换成你所使用的任何类型。使用。 So I wouldn't recommend this at all. 所以我根本不会推荐这个。


Another method of getting around this would be to set the DataContext in code-behind, and if you're going to do that, then, well, only God can save you now. 解决这个问题的另一种方法是在代码隐藏中设置DataContext ,如果你要这样做,那么,只有上帝现在可以救你。 The main ideas around the MVVM design pattern is the separation of View logic and the Business layer (View Models), as soon as your View starts instantiating view models then that nice separation is lost. 围绕MVVM设计模式的主要思想是View逻辑和业务层(View Models)的分离,一旦View开始实例化视图模型,那么很好的分离就会丢失。

Now saying that, there's nothing stopping you from doing this, I've said this many times before. 现在这样说,没有什么可以阻止你做这件事,我之前已多次这样说过了。 MVVM is a design pattern, not the law , if you want to set the DataContext in code-behind, then fair enough, however it's important that you are aware of the implications. MVVM是一种设计模式, 而不是法律 ,如果你想在代码隐藏中设置DataContext ,那么公平,但重要的是你要意识到其含义。

You could create a class that inherits from your generic ViewModel and use that 您可以创建一个继承自通用ViewModel的类并使用它

public class PersonViewModel : ViewModel<Person>

XAML: XAML:

<UserControl.DataContext>
    <s:PersonViewModel/>
</UserControl.DataContext>

You're not capable of setting a generic viewmodel in XAML because XAML requires known types at compile time. 您无法在XAML中设置通用视图模型,因为XAML在编译时需要已知类型。

Dependency injection is your best bet 依赖注入是最好的选择

public class MyControl : UserControl{     
   public MyControl(Object viewModel){    
      this.DataContext = viewModel;
   }
}

If your ViewModel is derived from a base class, let's say NonGenericViewModel then you can assign in code behind an object of type NonGenericViewModel to the DataContext. 如果您的ViewModel是从基类派生的,那么让我们说NonGenericViewModel然后您可以在代码中将NonGenericViewModel类型的对象分配给DataContext。 Using this way you still have the benefits of generics and the data binding will also work because the bindings will be made during runtime, no matter what type of object you assign to DataContext as long as it has properties, collections, etc required by your xaml controls. 使用这种方式你仍然可以获得泛型的好处,数据绑定也可以工作,因为绑定将在运行时进行,无论你分配给DataContext的对象是什么类型,只要它具有xaml所需的属性,集合等。控制。

BaseViewModel<T> : NonGenericViewModel { ... }

NonGenericViewModel : INotifyPropertyChanged { ... }

And in code behind, in the ctor of your xaml.cs: 在后面的代码中,在xaml.cs的ctor中:

NonGenericViewModel nonGenVM = new BaseViewModel<person>();
this.DataContext = nonGenVM;

Even this is correct and working: 即使这是正确和有效的:

this.DataContext = new BaseViewModel<Person>();

It depends if you need or not the class NonGenericViewModel in other places. 这取决于你是否需要在其他地方使用NonGenericViewModel类。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我如何将视图(具有自己的视图模型的数据上下文)与另一个视图模型的属性绑定 - How can i bind a view(having datacontext of own viewmodel) with another viewmodel's property 在WPF中,如何绑定到ViewModel并使各种XAML元素绑定到ViewModel的方法? - In WPF how can I bind to the ViewModel and have various XAML elements bind to the ViewModel's methods? 如何覆盖ViewModel DataContext,以便绑定到View中的对象(Mvvm-Light)? - How do I override the ViewModel DataContext so I can bind to objects in the View (Mvvm-Light)? 如何将ViewModel绑定到另一个XAML文件的ListView中的XAML文件? - How can I bind a ViewModel to an XAML file inside a ListView of another XAML file? 如何绑定到视图的DataContext而不绑定到最内部的DataContext? - How can I bind to the View's DataContext and not the innermost DataContext? 如何将 MainWindow.xaml 中的 8 个复选框绑定到 ViewModel 的字节属性的每一位? - How can I bind 8 checkboxes in MainWindow.xaml to each bit of a byte property of ViewModel? 如何在窗口的 DataContext 中将 DataContext 绑定到 ViewModel? - How to Bind a DataContext to ViewModel inside window's DataContext? 在XAML文件中未绑定DataContext - DataContext is not bind in the XAML file 在C#中,如何从ViewModel的视图上设置DataContext? - In C#, how can I set DataContext on a View from the ViewModel? 如何在XAML中设置从文件加载的ComboBox DataContext? - How can I set ComboBox DataContext that was loaded from a file, in XAML?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM