1

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

globetrotter
  • 997
  • 1
  • 16
  • 42
  • @FlowFlowOverFlow it's part of the toolkit, see ModelBase (and other definitions) of the toolkit here: http://simplemvvmtoolkit.codeplex.com/wikipage?title=Programming%20Reference – globetrotter Jun 28 '14 at 00:07
  • Try this: `NotifyPropertyChanged((B m) => m.AdditionalProperty);` – Gjeltema Jun 28 '14 at 00:57
  • @Gjeltema it gives me this: "Error: The type arguments for method '`SimpleMvvmToolkit.ModelBaseCore.NotifyPropertyChanged(System.Linq.Expressions.Expression>)`' cannot be inferred from the usage. Try specifying the type arguments explicitly" – globetrotter Jun 28 '14 at 01:17
  • Can you clarify what you mean by "here is now `NotifyPropertyChanged` looks like in `B`"? Do you mean that line exists in your `B` class? If so, remove it and try it out. I skimmed the Simple MVVM documentation, and I don't see it calling this ModelBaseCore class in the `NotifyPropertyChanged` implementation. http://simplemvvmtoolkit.codeplex.com/wikipage?title=Programming%20Reference – Gjeltema Jun 28 '14 at 01:47
  • @Gjeltema bad wording, it should be: here is what IntelliSense gives for `NotifyPropertyChanged` in `B` – globetrotter Jun 28 '14 at 01:51

2 Answers2

2

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.

Gjeltema
  • 4,122
  • 2
  • 24
  • 31
  • thanks @Gjeltema, I think I'll have to switch to another toolkit as suggested. Does MVVM Light also implement a Message Bus? I'm asking because the reason I tried Simple MVVM Toolkit in the first place was because of a suggestion I received from a question I asked yesterday: http://stackoverflow.com/questions/24438728/assigning-property-of-viewmodel-to-property-of-another-viewmodel-in-c-sharp-wpf – globetrotter Jun 28 '14 at 02:44
  • 1
    @globetrotter DeanK in your other question also recommended MVVMLight. Yes it does have a message bus implementation. You may also consider using the PRISM EventAggregator, or the .Net `EventManager` (new in .Net 4.5) for weak inter-VM communication. PRISM also has classes like `ViewModelBase` and quite a few other things that help with MVVM as well. I write a professional shrink-wrap WPF application, and use MVVMLight and PRISM in it, and they serve our needs quite well. (There's a lot of overlap between the two - we could make do with just one of them if we wanted). – Gjeltema Jun 28 '14 at 03:10
2

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.

Normal
  • 56
  • 2