Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Suppose we have a generic View model like this:

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 editor does not find My View Model class. How should I refer to a generic type in 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.

like image 685
a.toraby Avatar asked Jul 30 '15 16:07

a.toraby


1 Answers

When working with XAML, you cannot instantiate a view model with a generic parameter in XAML code.

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.

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. 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. 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. 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.

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.

like image 135
Mike Eason Avatar answered Sep 20 '22 17:09

Mike Eason