MVVM - RaisePropertyChanged turning code into a mess
Asked Answered
L

5

9

New to MVVM so please excuse my ignorance.

I THINK i'm using it right but I find my ViewModel has too many of these:

RaisePropertyChanged("SomeProperty")

Every time I set a property I have to raise that damned property changed.

I miss the days where I could just go:

public int SomeInteger { get; private set;}

These days I have to stick the "RaisePropertyChanged" in everywhere or my UI does not reflect the changes :(

Am I doing it wrong or are other people getting annoyed with the excessive number of magic strings and old school property setters?

Should I be using dependency properties instead? (I doubt that would help the code bloat anyway)

Despite these problems I still think MVVM is the way to go so I guess that's something.

Leix answered 31/3, 2010 at 12:46 Comment(2)
"I miss the days where I could just go" how easily we forget, in C#2 you couldn't do that at all. ;)Rabbi
ya i guess i got spoiled but despite the progress being made, I still think there could be a cleaner way to implement this stuff. I don't know the inner workings/tradeoffs enough though...Leix
M
12

Take a look at this What is the best or most interesting use of Extension Methods you've seen?.

It describes an extension method and a helper method that my Model and ViewModel classes use to enable the following strongly typed (no magic string) properties.

private string _name;
public string Name
{
    get { return _name; }
    set { this.NotifySetProperty(ref _name, value, () => this.Name); }
}

This is about as simple as I think it can get. Hope it helps.

Married answered 31/3, 2010 at 13:0 Comment(1)
Thanks. kinda glad to know I wasn't the only one having issues.Leix
D
7

You could use PostSharp's NotifyPropertyChanged attribute. Then all you have to do is to put an attribute on the class and that's it. E.g.:

[NotifyPropertyChanged]
public class MyClass 
{
    public string MyProperty { get; set; }
}
Debate answered 31/3, 2010 at 13:54 Comment(4)
There's no runtime overhead since PostSharp simply modifies the compiled class and injects exact same code you write manually. There's a small build time overhead but I found it negligible.Debate
The only drawback to this approach is that sometimes it's necessary to RaisePropertyChanged for a property other than the one where the setter is being invoked.Search
Disclaimer: PostSharp is commercial software and the starter (free) edition does not support this attribute.Thermoluminescent
Use superior and free alternative: Stepen Cleary's Calculated Properties. github.com/StephenCleary/CalculatedProperties/blob/master/… I used both in production and it's far more flexible than PostSharp's aspect. None of postsharp limitations apply to Calculated Properties. It can wire dependencies from loops, virtual methods, LINQ to objects, basically any crazy runtime dependencies that you can imagine doesn't matter how indirect, dependency graph rewires itself at runtime and just works without any ceremony. They are also fast. Boilerplate code is minimal too.Chromatophore
L
4

It helps to look at things from a different perspective: those are not complicated .NET properties, but simplified dependency properties.

Bindable properties of a view model in WPF are not identical to .NET properties, instead it is a kind of key-value store. If you want light-weight alternative to DependencyObject, you have an ability to implement this key-value store just buy calling certain function in setters - not bad, actually. Far from ideal too, of course, but your point of view is certainly unfair.

Lollop answered 31/3, 2010 at 13:51 Comment(0)
B
0

It does not get you back to the clean code, but I use a simple extension method to get the property name to avoid problems with magic strings. It also maintains the readability of the code, i.e. it is explicit what is happening.

The extension method is simply as follows:

public static string GetPropertyName(this MethodBase methodBase)
{
    return methodBase.Name.Substring(4);
}

With this it means that you property sets are resilient against name changes and look like the following:

private string _name;
public string Name
{
    get { return _name; }
    set 
    {
            name = value;
            RaisePropertyChanged(MethodBase.GetCurrentMethod().GetPropertyName()); 
    }
}

I've written more about this extension method here and I've published a matching code snippet here.

Bebeeru answered 16/5, 2011 at 8:6 Comment(1)
Old question, i know :) Another way is to encapsulate the RaisePropertyChanged inside a base class and use the following method signature: OnRaisePropertyChanged([CallerMemberName] propertyName = ""). This way you can call the method without needing to write the property nameArgil
E
0

This will help: "Kind Of Magic" Effortless INotifyPropertyChanged

[http://visualstudiogallery.msdn.microsoft.com/d5cd6aa1-57a5-4aaa-a2be-969c6db7f88a][1]

as an example for adding it to one property:

[Magic] 
public string Name { get { return _name; } set { _name = value; } } 
string _name;

Another example for adding it to all the class properties:

[Magic] 
public class MyViewModel: INotifyPropertyChanged 
{ 
  public string Name { get; set; } 
  public string LastName { get; set; } 
  ..... 
}
Eddieeddina answered 5/11, 2013 at 12:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.