Question

I have a window, containing a nested control NC1 which contains 3 instances of nested control NC2. I have a "reset" button on NC1 that is supposed to reset the values of NC1 and all three NC2s within the NC1.

I have tried several implementations of the Reset button and non have been successful. In all cases, the HasDirtyModel remains true even though the data resets.

I have tried explicitly calling ((IEditableObject)nc2).CancelEdit() on all three instances of NC2 and ((IEditableObject)nc1).CancelEdit(). While this completely resets, doing only the CancelEdit on NC1 did not reset the NC2 models. (NC1's view model has a property with [Model] and [Expose("NC2s")] which is a List in the NC1 model.

Calling CancelViewModel() does also reset the data, but still leaves HasDirtyModel set true.

All of the models do derive from ModelBase. What should I be doing to cause the HasDirtyModel to become false.

This issue is with a WPF application using Catel 3.9

Was it helpful?

Solution 2

So the simple (I hope) solution is to create a IsModelDirty property at the model level. Avoid IsDirty because it is not overrideable and setting it false is enough to set the model dirty again (ie IsDirty becomes true). Override OnPropertyChanged in the Model and set your IsModelDirty true in it. In my case there is no need to ensure that the property being changed is NOT IsDirty because of my flow of control. The framework has already set it True and neither the framework or I ever set it False again. In my Model constructor I set LeanAndMeanModel to true. I override OnBeginEdit, OnEndEdit and OnCancelEdit in the Model. The code for each of them is below.

/// <inheritdoc />
protected override void OnBeginEdit (System.ComponentModel.BeginEditEventArgs e)
{
  base.OnBeginEdit(e);
  IsModelDirty = false;
  LeanAndMeanModel = false;
}/* method TLModelBase OnBeginEdit */

/// <inheritdoc />
protected override void OnCancelEdit (System.ComponentModel.EditEventArgs e)
{
  LeanAndMeanModel = true;
  base.OnCancelEdit(e);
  IsModelDirty = false;
  LeanAndMeanModel = false;
}/* method TLModelBase OnCancelEdit */

/// <inheritdoc />
protected override void OnEndEdit (System.ComponentModel.EditEventArgs e)
{
  LeanAndMeanModel = true;
  base.OnEndEdit(e);
  IsModelDirty = false;
  LeanAndMeanModel = false;
}/* method TLModelBase OnEndEdit */

Lastly, override HasDirtyModel to access IsDirtyFlag for each Model registered for the ViewModel by using GetAllModels().

OTHER TIPS

Catel does not support the combination of Cancel and HasDirtyModels. Internally Catel subscribes to the models using INotifyPropertyChanged. As soon as events are raised and values are different, a model is considered dirty.

Unfortunately a model can implement IEditableObject without the option to subscribe from the outside world. This makes it impossible (or at least very performance-costly) to check if a model is rolled back every time. This can only be "fixed" by keeping track of a fully cloned object graph and comparing whether the current object graph is fully equal to the original one.

This would require complete graph cloning for every model on the view model which is simply too performance-costly (especially with ARM platforms in mind).

One simple solution is to keep track of the reset states yourself. You are the only person that knows when the CancelEdit is called. This means that you can set _hasDirtyModels on your VM and reset that when you call CancelEdit.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top