Currently I'm working with some UI code which has a 'domino effect' when a property changes on a view model - the data is being rendered in a tree view, and the reason for the 'domino effect' is because the value of a node in the tree view is an aggregation of multiple child nodes (leaf nodes hold the actual values which are aggregated up). The dataset is dynamic, it can be updated during it's visualization and when this happens we want the ability suspend NPC events being fired until recalculating all the aggregates has completed.
I have the following base class for all bind-able (view model) classes:
What I wanted was the ability toprevent suspend the firing of the PropertyChanged event and then resume later, I wanted to do this via a single new method exposed on this class and the return type would IDisposable and importantly it should reference count when called multiple times without being disposed. I wanted the ability to do something similar to the following test - where I can have nested calls to suspend but it will only resume when the underlying reference count returns to zero:
I wanted minimal changes to the Bindable class - I wanted to avoid increasing the memory foot print of class as much as possible as well as only adding a single public method to the class. Ideally I wanted the Bindable class to have no knowledge directly of the reference counting going on when nested calls to SuspendNotifications method are made.
I came up with the following changes to the Bindable class:
As you can see the only change to the public signature is the addition of the SuspendNotifications method and the internal structure now has a reference to a disposable instance. The RaisePropertyChanged method has been modified to check whether notification have been suspended - if they have then it is added to the instance of the SuspendedNotification class:
Looking at the method above what you notice is the returned IDisposable is not the instance of the SuspendedNotification class but the one returned by the call to the AddRef method. Every time the IDisposable returned by the AddRef method is disposed the reference count on the instance of SuspendedNotifications is decremented, once this returns to zero the property changed events are fired for all the properties which have changed whilst notifications have been suspended.
This is all achieved by the parameter passed to the SuspendedNotifications class - basically I've inverted the responsibility for when the SuspendedNotifications instance is disposed, the instance disposes of it's self when the reference count returns to zero. This can be seen in the SuspendedNotifiication class below:
I have the following base class for all bind-able (view model) classes:
What I wanted was the ability to
Loading ....
The User class is shown below:
Loading ....
I came up with the following changes to the Bindable class:
As you can see the only change to the public signature is the addition of the SuspendNotifications method and the internal structure now has a reference to a disposable instance. The RaisePropertyChanged method has been modified to check whether notification have been suspended - if they have then it is added to the instance of the SuspendedNotification class:
Loading ....
The SuspendNotifications method is defined as follows, as you can see there isn't much to the method, you're probably wondering - 'when does the created instance of SuspendedNotifcations get disposed?'
Loading ....
The answer is when the internal reference counter of the SuspendedNotifications class returns to zero.Looking at the method above what you notice is the returned IDisposable is not the instance of the SuspendedNotification class but the one returned by the call to the AddRef method. Every time the IDisposable returned by the AddRef method is disposed the reference count on the instance of SuspendedNotifications is decremented, once this returns to zero the property changed events are fired for all the properties which have changed whilst notifications have been suspended.
This is all achieved by the parameter passed to the SuspendedNotifications class - basically I've inverted the responsibility for when the SuspendedNotifications instance is disposed, the instance disposes of it's self when the reference count returns to zero. This can be seen in the SuspendedNotifiication class below:
Loading ....
And this produces a successful test output:
Do you mind sharing the source code please?
ReplyDelete