There are two ways to get notified of changes made withing a command:
- CommandDone event (in UndoRedoManager)
- Changed event (in particular UndoRedo property, list or dictionary)
CommandDone event is fired after any command has been commited/undone/redone. It is fired once per command despite how many changes were in the command.
Changed event provides much higher level of granularity. It is fired when particular property/list/dictionary was changed during a command.
In this post I will tell more about the Changed event. This event provides very precise control on what data notifications you receive. Subscribtion is fairly simple:
class DataClass
{
internal readonly UndoRedo<int> prop1 = new UndoRedo<int>(0);
public int Prop1
{
get { return prop1.Value; }
set { prop1.Value = value; }
}
public Subscribe()
{
prop1.Changed +=
new EventHandler<MemberChangedEventArgs>(prop1_Changed);
}
}
Besides of precision, Changed event guaranties data consistency for subscriber. In other words, subscriber may always assume that all data is in consistent state despite on order of how data was changed. For example, we subscribe on Prop1 changes. The point is that our handler may rely that Prop2 is consistent too even if it was changed later in the command.
This magic happens because Changed event is not fired immediately but waits untill the command is commited. And this is the most important thing you have to understand: firing of Changed event is postponed to the point where all data is in consistent state and commited.
This advantage allows you to selectively update UI layer with confidence that changed property and any other data properties can be correctly displayed. So, you can write very intelligent and reliable MVC/MVVM pattern even for complex cases.
Another notes are:
- If command was cancelled, there will not be any Changed event;
- If a property was changed ten times during the command, Changed event will be fired once for this property when command commited;
- Changed event will also be fired when the same command is Undone/Redone;
- You can assign Owner and Name to the property. It usefull when one handler subscribed on several properties at once:
prop1.Owner = this;
prop1.Name = "Prop1";
prop2.Owner = this;
prop2.Name = "Prop2";
...
void prop_Changed(object sender, MemberChangedEventArgs e)
{
if (e.Member.Name == "Prop1")
{...}
}