简体   繁体   中英

“Simple MVVM Toolkit” child Model classes in C# WPF

I'm using " Simple MVVM Toolkit " ( MVVM noob here) to develop a C# WPF app.

I have a model class called A :

public class A : ModelBase<A>
{
    //properties, constructors, methods..
}

..and another model class called B which inherits from A but exposes a property which A doesn't have:

public class B : A
{
    private string additionalProperty;
    public string AdditionalProperty
    {
        get { return additionalProperty; }
        set
        { 
            additionalProperty = value; 
            //NotifyPropertyChanged(m => m.AdditionalProperty); <-- problem here
        }
    }
}

Problem comes with the commented line above: the lambda in NotifyPropertyChanged won't work because m.AdditionalProperty doesn't exist, since m is of type A , not B . What happens in this case? I should note that NotifyPropertyChanged comes with the toolkit and is not a custom implementation.

EDIT : Here is the IntelliSense description for NotifyPropertyChanged in B :

void ModelBaseCore<A>.NotifyPropertyChanged<TResult>(System.Linq.Expressions.Expression<Func<A,TResult>> property)

Allows you to specify a lambda for notify property changed

The problem is in how they implemented the ModelBase . They obviously didn't feel that someone would be subclassing a model that subclasses from ModelBase , which I'm not sure why they'd think that.

In any case, the issue is that you're telling the ModelBase what type to use to do its resolution when you specify the generic: ModelBase<A> . To get around this, you have to do some rather convoluted generic play that looks pretty goofy:

public class A<T> : ModelBase<T> where T : A<T>
{
    //properties, constructors, methods..
}

public class B : A<B>
{
    private string additionalProperty;
    public string AdditionalProperty
    {
        get { return additionalProperty; }
        set
        { 
            additionalProperty = value; 
            NotifyPropertyChanged(m => m.AdditionalProperty);
        }
    }
}

Note that A now inherits from ModelBase<T> not ModelBase<A> , and you constrain T to be A<T> . Then you have B inherit from A and specify its generic as B (which implements A<T> ).

This is rather convoluted, and I'm not sure why they did it this way - possibly because there's some cross-platform things that require them to do this. If you don't need this for cross-platform work, or possibly they didn't do this for that reason, I would instead recommend you use something like MVVM Light for your MVVM needs. It has a different implementation for the NotifyPropertyChanged that doesn't depend on specifying its own type, and reduces the need for this over-use of generics.

You're not limited to the properties on the parameter passed into the lambda. You can also use properties on any object that's referable within the parent set of curly braces(in your case the setter). Including "this".

Instead of:

NotifyPropertyChanged(m => m.AdditionalProperty);

Try:

NotifyPropertyChanged(m => this.AdditionalProperty);

If you dig through the source, the string value of the property that is passed in is derived from the Expression parameter itself. Aside from using the object to get it's property it's not used at all. It could come from "this", some other object entirely, etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM