Implementing INotfyPropertyChanged for calculated properties - c#

I'm a bit new to MVVM, and was wondering
Let's say I have defined a ObservableCollection<Differences> Diffs property.
I also have the following property:
public bool IsSame
{
get
{
return Diffs.Count == 0;
}
}
I dont get how I'm supposed to implement the OnPropertyChanged for IsSame, because it is implicit from the Diff list.
Should I attach to the List OnCollectionChanged event and then check if it changes IsSame ?
Should I use a backing field anyway and handle the List OnCollectionChanged?
Thank you very much.

Should I use a backing field anyway and handle the List OnCollectionChanged?
To do it correctly: Yes.
When related properties change it's up to the source to raise all events. Your main problem here is to detect when IsSame actually changes (ie goes from 1 to 0 or from 0 to 1). You need either a backing field or you will raise the event (much) more often then is required.

when ever you collection changes you should call OnPropertyChanged("IsSame"); - thats right. but when to call depends on your viewmodel logic.
edit: assume that you have an Add and Remove command, then you have to call OnPropertyChanged("IsSame"); within these methods.

Related

In WPF two-way binding, how can you check if it was a UI element or ViewModel that triggered the binding change?

I'm not sure what keywords to search for...lost in a sea of Google.
I have a two-way databinding specified between a visual element (slider bar) and a numeric value in my ViewModel. I want to differentiate between when a value change is user-initiated vs ViewModel-based, so that I can selectively trigger an event elsewhere in my application. How can I do this in the code-behind of the XAML file?
Update 2015-02-26: In reply to Amit's question, WHY I need this capability is that I actually have more than one visual element set up for 2-way databinding to the same ViewModel source, so not differentiating leads to an infinite loop (stack overflow) in callbacks to dependent code that itself has the ability update the same values.
Aside - shouldn't there be reputation points for the first time one appropriately ues "stack overflow" on SO?
Your best bet is not to have two different behaviors. You need to fire the same notifications and recalculate the same dependent properties either way. But I've run into cases where, say, sometimes I want to fire off an animation and sometimes I don't, so different behaviors can be necessary.
If you really do need two different behaviors, I would just make two different properties (or a property and a method). Bind one property to the UI, and use the other when you're setting the value programmatically. Give each one the side effects it needs to have.
Not only does this keep things simple, it also means you can write unit tests for both sets of behaviors.
I think the short answer is: not really.
When you bind to a ViewModel property from your XAML element, ultimately the WPF binding system will call the property setter in the ViewModel. Once inside the setter method you have no context as to how you got there. You could possibly check the stack to see where you came from but that would be very brittle code and presumably quite slow as well.
If the property was only being set by either the XAML binding or by the ViewModel, then you could set some kind of Boolean flag in your ViewModel like so:
bool _isBeingSetByVM;
public int Number
{
get { return _number; }
set
{
if (_isBeingSetByVM)
{
// ViewModel has set the property
// Do whatever you need to do...
_isBeingSetByVM = false;
}
if (_number != value)
{
_number = value;
OnPropertyChanged("Number"); // generate PropertyChanged event
}
}
}
int _number;
void SomeMethodInVM()
{
_isBeingSetByVM = true;
Number = 42;
}
But again, this is very brittle code that is hard to maintain. As #Amit says in his comment, the better question might be why you need to do this.

How to notify UI of change with readonly property?

In WPF, I have a property with only a get{}. The value is coming from the return of method. NotifyPropertyChanged is often used within a property set{}. It can then notify the UI and the updated value is displayed. But with a get{} only, there isn't a way of detecting if a new or different value is available since you have to execute the method to check.
Is there some way to update the UI without having to keep a local value that contains the last value from the method, in which case a compare would need to be done?
But with a get{} only, there isn't a way of detecting if a new or different value is available since you have to execute the method to check.
The problem boils down to this: What is changing the property? The method that changes the property should call your NotifyPropertyChanged with the name of the property, which will, in turn, cause WPF to refetch the value and update the user interface.
WPF doesn't care where the PropertyChanged event gets raised - it just listens for it, and refreshes the binding as needed.
Edit in response to comment:
It sounds like this may be the result of performing some operation upon your Model class. In this case, it's common that you know that one or more properties may change, but not necessarily which ones. If your Model implements INotifyPropertyChanged, you can subscribe to that and "bubble up" the notifications to the UI via your NotifyPropertyChanged method. If it does not, however, there is another option.
If you know that one or more properties may change, you can raise a PropertyChanged event with string.Empty as the PropertyName in the EventArgs. This will cause all bound properties to get refreshed by WPF. This is likely just a matter of putting something like this in your code:
this.Model.DoSomething(); // This will change 1+ properties
this.NotifyPropertyChanged(string.Empty); // Refresh our entire UI
I wouldn't recommend doing this everywhere, however, as it does add overhead - but it's often the cleanest solution if you don't know which properties will change when you perform an operation.
Yes. Where you change the source data you would need to fire the INotify on the property. Here is an example.
private int _myvalue = 3;
public bool MyProperty
{
get { return IsAProperty(); }
}
public bool IsAProperty()
{
return _myvalue + 1 == 4;
}
public void SetValue(int value)
{
_myvalue = value;
NotifyPropertyChanged(MyProperty);
}

Least cpu intensive method of checking if a list has changed in c#

I have a function that is to be called if a list has changed since it was last called, what would be the best way of implementing this?
ex:
List<A> OurList = new List<A>();
private void Update()
{
Boolean Changed = //?
if(Changed) CheckList(OurList);
}
I would have assumed make a variable to store the old list and compare, but how would I update the old list to the new list without copying it all out? (If I do an assign, it will update the "old list" too)
Use an ObservableCollection<T> instead of a List, then subscribe to the CollectionChanged event.
This way, you will be told when the list is changed instead of having to scan the data to figure out what happened after the fact.
The most efficient way would be to wrap the List<> in your own class and have all the mutating methods (Add, Remove) set a boolean flag.
Your Method can then just look at that flag and reset it.
If you're using .NET 4.0, you could use the ObservableCollection class. (prior to 4.0, you would need to reference WPF).
Once you create your list, just add a handler to the CollectionChanged event.
Your best bet would be to use an ObservableCollection<T> or BindingList<T> to get push notification of a change. You could also subclass Collection<T> if you want any custom behaviour.
To answer your question as asked (except for the cpu-intensive bit), you can use an existing feature of List<T>: it maintains its own version internally so that it can throw if the collection has changed during enumeration.
This is based on analyzing code from reflector. It is not part of any contract, so it is liable to break at any time. It may also not work in a partial-trust environment. Please use with care:
public static int GetVersion<T>(this List<T> list)
{
return (int)list.GetType()
.GetField("_version", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(list);
}
...
private int _lastCheckedVersion = 0;
private void Update()
{
int currentVersion = ourList.GetVersion();
if(currentVersion != _lastCheckedVersion) CheckList(ourList);
_lastCheckedVersion = currentVersion;
}
Restrict access to the list.
Allow changes only through a prescribed API.
In that API, set a flag whenever the ChangeList method is called.
Are you trying to see if the List itself changed (adding/removing items), or if an item on the list changed.
If you're simply looking to see if a list had an item added/removed, the easiest would be to wrap the List in a new class and override the Add/Remove methods for your object to trigger a boolean.
The more complicated requirement is if you need to know if an item contained on the list has changed (a property or field in the class object that is referenced in the list). If that's the case, it depends on your specific situation. You could put in the setter for the properties for those classes a way to trigger a boolean that would do the same thing as before. But this depends on the complexity of the class in the generic list.

Should a setter return immediately if assigned the same value?

In classes that implement INotifyPropertyChanged I often see this pattern :
public string FirstName
{
get { return _customer.FirstName; }
set
{
if (value == _customer.FirstName)
return;
_customer.FirstName = value;
base.OnPropertyChanged("FirstName");
}
}
Precisely the lines
if (value == _customer.FirstName)
return;
are bothering me. I've often did this but I am not that sure it's needed nor good. After all if a caller assigns the very same value I don't want to reassign the field and, especially, notify my subscribers that the property has changed when, semantically it didn't.
Except saving some CPU/RAM/etc by freeing the UI from updating something that will probably look the same on the screen/whatever_medium what do we obtain?
Could some people force a refresh by reassigning the same value on a property (NOT THAT THIS WOULD BE A GOOD PRACTICE HOWEVER)?
1. Should we do it or shouldn't we?
2. Why?
Yes, you should return immediately when the consumer is setting a property value that is equal to the value which is already being persisted.
First of all, there is no reason to waste any time or resources in the setter of the property - the value is already set so no further action is needed. Also you should never call OnPropertyChanged if the value stored in the property's backing field hasn't changed - the method is intended to be raised when the value has changed not when the property's setter has been called.
All that being said, however - if the setter didn't have a call to OnPropertyChanged I wouldn't have bothered to check the value first. In the case of a simple setter that only sets the backing field's value and nothing else it is actually going to be faster to always the set the value rather than checking first then setting the value. Only use this pattern when the property's setter has additional logic that either shouldn't fire or may incur an unnecessary performance penalty.
Or you could do this:
set
{
if (value != _customer.FirstName)
{
_customer.FirstName = value;
base.OnPropertyChanged("FirstName");
}
}
No need for multiple return paths.
To further answer your question, I wouldn't force an update to property if it's being overwritten by the same value. There's really no point, because you're probably not going to get any benefit from it. (I could see an instance where you would want to track each time someone tries to update a value.)
The only argument against that pattern (where you return if the value hasn't changed) I can think of is the purist's view that every function should have only one exit. Not being a purist, I don't agree. I see nothing wrong with breaking out if the value hasn't changed, avoiding the notification update.
The only situation when you shouldn't use it is when you know that you can have dirty data on your class, for example on a ORM layer object that might have outdated values compared to the underlying database because of modification by another user.
If that situation doesn't affect you, then cache away!
Edit
I misunderstood your question, as you are talking about setters, not getters.
Similar points apply. If the set operation is a costly one, and is not supposed to have any kind of side effect (it should't! Side effects on setters are <blink>evil</blink>!!1), then it's a valid optimization.
One reason to not return early, I would imagine, is for subscribers that joined the party late. They might not be aware of the object's current state, and will miss out on the setter notification if you return early.
Most of times those properties are used in binding. But as soon as you start using NotifyPropertyChanged event yourself (in own markup extenstions, behaviors, between VM in MVVM, etc.) you will realise you just want this event to always occurs.
To me this check (notification protection) is kind of premature optimization. I am often rising event with "" as propertyName to just refresh bindings or force event for some custom stuff and that alone is much more costly.
I don't see a need to protect each property. Why? From what kind of operation? Animations are running on dependency properties. User updates (when view bindings are updating source) are anyway slow. And for any update rised from within code behind you are pretty much need event to be rised.
To me it looks like a pattern, invented without much reasons and followed blindly. Of course there are cases when you need to prevent property setter code from being running under certain conditions. And that's ok if you add such checks to solve certain performance issue then. But not in advance.

PropertyChanged affecting several properties

I have a situation where I have a couple of variables who's values depend on each other like this:
A is a function of B and C
B is a function of A and C
C is a function of A and B
Either value can change on the UI. I'm doing the calculation and change notification like this:
private string _valA;
private string _valB;
private string _valC;
public string ValA
{
get { return _valA; }
set
{
if (_valA != value)
{
_valA = value;
RecalculateValues("ValA"); //Here ValB and ValC are calculated
OnPropertyChanged("ValA");
}
}
}
public string ValB
{
get { return _valB; }
set
{
if (_valB != value)
{
_valB = value;
RecalculateValues("ValB"); //Here ValA and ValC are calculated
OnPropertyChanged("ValB");
}
}
}
(...)
private void RecalculateValues(string PropName)
{
if (PropName == "ValA")
{
_valB = TotalValue * _valA;
OnPropertyChanged("ValB");
_valC = something * _valA
OnPropertyChanged("ValC");
}
else
(...)
}
I'm calling the calculation method on the setter of the changed variable, calculating the values for _valB, _valC (for example) and then calling PropertyChanged for these ones.
I do it like this because of the dependencies between the variables, like this i can control which variable gets calculated with the correct values. I also thought about triggering the PropertyChanged for the other variables and perform the calculation on the getter of the variables but i would have to know which property changed before and use that value...not sure if it's the best/simplest solution.
Is this a good way to do this? I don't like the idea of performing this on the setter block, but at the time I can't see any better way to do it.do you see any other (better or cleaner solution)?
Another issue I have is using IdataErrorInfo for validation/presenting error info to the UI.The thing is the this[columnName] indexer gets called at the end of the setter and I needed to validate the values before the calculation, so that if the value inputted is not valid the calculation would not happen.I'm seriously considering abandoning IDataErrorInfo and simply calling my validation method before the calculation(s) occurs. Is there any way to explicitly calling it or right after the value attribution?
NOTE: ValidationRules are not an option because I need to call validation logic on another object from my ViewModel.
Its alright to call your Validation and Calculation in Setter, as long as it does not block the thread and goes into heavy cpu intensive calculations. If you have simple 5 to 10 math based statements without involving complex loops, its alright.
For databinding and WPF, this is the only way, However there is one more implementation called IEditableObject which has BeginEdit, CancelEdit and EndEdit, where you can do your calculation and validation on "EndEdit" function.
In BeginEdit, you can save your all values in temp storage, in CancelEdit you can bring back all values from temp and fire PropertyChaged event for all values those were modified and in EndEdit, you can finally update all variables and fire PropertyChanged for all those are updated.
IEditableObject will be best for performance wise, but it may not display new values until it was cancelled or ended, however to display instantly the only way to do is the way you are doing it.
In case of heavy cpu usage, you can invoke another thread to do calculation and set variables and at the end you can fire PropertyChanged, but yes technicaly you are just doing same thing while setting value in setter but asynchronously.
Since you can evoke NotifyPropertyChanged from anywhere in the class, one way to simplify this is to have your Calculate method fire the NotifyPropertyChanged for all three variables. I use this trick when I have complex calculations with multi-dependencies. Sometimes you'll still want to fire the event in the Setter: in that case I use a flag field to disable the event when I am updating the property from within the Calculations so that the event is not fired twice.

Categories

Resources