Skip to content

ViewModel Base

JP edited this page Jan 10, 2021 · 3 revisions

The base of every MVVM pattern.

ThreadSaveViewModelActor

The ViewModelBase inherts from ThreadSaveViewModelActor, the base class for all ViewModel components of WPFToolsAwesome. The ThreadSaveViewModelActor can enqueue actions into an set dispatcher and can also track what Dispatcher to use. This is very important in an multi Dispatcher process. The ThreadSaveViewModelActor main functions are the ViewModelAction(Action action, DispatcherPriority priority = DispatcherPriority.DataBind) and BeginViewModelAction(Action action, DispatcherPriority priority = DispatcherPriority.DataBind). Both take care of the state of the Dispatcher and will also prevent oversubscription.

Oversubscription. When an operation enqueues another operation while the subscribing operation is already executing inside the Dispatcher Thread. This uses far more resources as necessary as the operation can be executed directly within the callers context instead of bothering the Dispatcher

Also all actions enqueued via Begin/ViewModelAction are all enqueued into the Dispatcher as DataBind priority. This helps keeping your WPF application responsible.

ViewModelBase

MVVM basics

This class should be one of the two base classes every ViewModel should inhert. It contains the Implementation of INotifyPropertyChanged & INotifyPropertyChanging. Directly implemented are they as SendPropertyChanged(string|Expression) and SendPropertyChanging(string|Expression) and both are using the CallerMemberNameAttribute. There are extensions that functions as alias for these methods that cover most variants of those names like RaisePropertyChanged, OnPropertyChanged, FirePropertyChanged.

Changetracking

ViewModelBase also contains an ChangeTracking mechanism that is covered by the IAcceptPendingChange interface. To use this Interface you must use the SetProperty method to set your properties.

Example:

ctor()
{
	PendingChange += OnPendingChange;
}

private void OnPendingChange(object sender, AcceptPendingChangeEventArgs e)
{
	e.CancelPendingChange = true | false; //setting this to true will stop the update
	e.NewValue //readonly
	e.OldValue //readonly
	e.PropertyName //readonly
}

private string _text;
public string Text
{
	get { return _text; }
	set { SetProperty(ref _text, value); }//SetProperty will raise the PendingChange event
}

Then you can attach yourself to the PendingChange event of that given ViewModelBase and use the CancelPendingChange property of that event arg to cancel the property setting operation. The same event arg contains also the new value and the property name.

DeferedNotification

Sometimes you want to make a lot of changes in bulk to a ViewModel. In that case its better to turn of the event handling of the INotifyPropertyChanged event and resume it later. This is implemented directly into the ViewModelBase by using the DeferNotification and ResumeNotification methods.

Example:

private string _text;
public string Text
{
	get { return _text; }
	set { SetProperty(ref _text, value); }//SetProperty will raise the INotifyPropertyChanged.PropertyChanged event
}

public void DoStuff()
{
	Text = "Hello World"; //this will set the property and immediately raise the PropertyChanged event
	using (DeferNotification())
	{
		Text = "H";//all this calls will set the property but will not raise the event
		Text = "E";
		Text = "L";
		Text = "L";
		Text = "O";
		Text = " World";
	}//only when the scope is disposed all gathered property names will be raised
}