Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it correct to call a method inside a Property Setter?

Tags:

c#

wpf

In a WPF application I'm working on I came across following code snippet;

public int SomeInteger
{
    get { return _someInteger; }
    set
    {
        _someInteger= value;
        OnPropertyChanged("SomeInteger");
        SomeIntegerChanged();
    }
}

As you can see, inside the property setter a method is called. Is this approach correct or is there any better way to do in MVVM pattern WPF?

As above code snippet is a sample, actually the property setter might load a DataTable when the property changes which might be time consuming. I tried to make the application asynchronous using async and await but above scenarios causes problems since async and await doesn't have asynchronous property concept.

I also got across a way to bind a event to INotifyPropertyChanged and by checking which property triggers the event and call the method. But looking for any other alternatives.

like image 955
Irshad Avatar asked Sep 04 '25 17:09

Irshad


2 Answers

Is this approach correct or is there any better way to do in MVVM pattern WPF?

This is, unfortunately, the common and accepted MVVM pattern across all of C#. I say "unfortunately" because this pattern does run into problems. It is based on events - which are problematic just on their own - and it also causes an immediate update, which in many cases is not desired.

For one example, sometimes it's desirable to have two properties that are mutually dependent - when the user changes one, the other one changes in relation to it - and this can cause problems since there's no way to distinguish "user changes" from "code changes".

For another example, sometimes you can end up with a whole tree of dependent properties, and it can take some time for all the changes to propagate through and stop interfering with each other.

More modern MVVM approaches like the atomically-updated single source of truth with single-directional data flow (as popularized by Redux) avoid the above problems. There is a C# Redux implementation; I don't know how easy it is to use. In my own CalculatedProperties library, I built my own "invalidation queue" to work around this, which defers all PropertyChanged updates until after the entire system's new steady-state is calculated.

I tried to make the application asynchronous using async and await but above scenarios causes problems since async and await doesn't have asynchronous property concept.

True. In particular, you can't "asynchronously get" a property. And this makes sense in the MVVM world; when WPF is updating the screen, and it asks your VM for a data value, then your VM can't say "hold on, I'll get it in a minute". WPF needs to know that value now so it can update the screen now.

Hooking up an asynchronous event handler is one way of kicking off asynchronous work when the value changes; that approach is fine. Usually, the presence of SomeIntegerChanged implies that there is a "changed" event specifically for that property, so hooking into PropertyChanged with string comparisons is probably the harder way to do it.

For more on asynchronous properties with MVVM, see my article on the subject.

like image 141
Stephen Cleary Avatar answered Sep 07 '25 12:09

Stephen Cleary


In this case, calling the methods in the Setter is okay. Using INotifyPropertyChanged for property change notifications in WPF is the correct way, and adding the call to the Setter is the default way to implement it.

The call to SomeIntegerChanged(); depends a bit on what the method does (and if it's even required given you already implemented INotifyPropertyChanged).

Using properties as a consumer should have as little side-effects as possible, and generally should be simple operations. There's a nice guide on MSDN about that topic.

You should also avoid using strings of property names as parameters, in your case the call to OnPropertyChanged should look like this: OnPropertyChanged(nameof(SomeInteger));

like image 21
Lennart Avatar answered Sep 07 '25 11:09

Lennart