I'm trying to make a "Dirty" implementation with Catel.
I have a viewmodel, with a [Model]
property and a few [ViewModelToModel]
mapped to it.
And I added a boolean member _canGetDirty
, that when set to true
allows viewmodel properties to prompt a service for saving.
So my logic is that if the model property changes, _canGetDirty
is set to false
, so the viewmodel properties change without getting dirty, and when the model is done changing we set _canGetDirty
to true
anew.
The problem is that the PropertyChanged
event for the model property is called before the viewmodel properties are changed, hence _canGetDirty
is always true, and my service is called for saving whenever I load a new model.
How to work around this issue?
public class MyViewModel : ViewModelBase
{
private IMyService _myService;
private bool _canGetDirty;
public MyViewModel(MyModel myModel, IMyService myService)
{
MyModel = myModel;
_myService = myService;
}
[Model]
public MyModel MyModel
{
get { return GetValue<MyModel>(MyModelProperty); }
set
{
_canGetDirty = false;
SetValue(MyModelProperty, value);
}
}
[ViewModelToModel("MyModel")]
public string Prop1
{
get { return GetValue<string>(Prop1Property); }
set { SetValue(Prop1Property, value); }
}
[ViewModelToModel("MyModel")]
public string Prop2
{
get { return GetValue<string>(Prop2Property); }
set { SetValue(Prop2Property, value); }
}
[ViewModelToModel("MyModel")]
public string Prop3Contains
{
get { return GetValue<string>(Prop3Property); }
set { SetValue(Prop3Property, value); }
}
#region Registering
public static readonly PropertyData Prop1Property = RegisterProperty("Prop1", typeof(string), null, PropertyToSaveChanged);
public static readonly PropertyData Prop2Property = RegisterProperty("Prop2", typeof(string), null, PropertyToSaveChanged);
public static readonly PropertyData Prop3Property = RegisterProperty("Prop3", typeof(string), null, PropertyToSaveChanged);
public static readonly PropertyData MyModelProperty = RegisterProperty("MyModel", typeof(MyModel), null, MyModelChanged);
#endregion
#region Property Changed Handlers
private static void MyModelChanged(object sender, PropertyChangedEventArgs e)
{
(sender as MyViewModel)._canGetDirty = true;
}
private static void PropertyToSaveChanged(object sender, PropertyChangedEventArgs e)
{
var vm = sender as MyViewModel;
if (vm._canGetDirty)
vm._myService.AskForSaving();
}
#endregion
}
Edit: some explanation on how Catel works in this context.
Registered properties changes:
We register properties that will notify updates with RegisterProperty
:
public static readonly PropertyData Prop1Property = RegisterProperty("Prop1",
typeof(string), null, PropertyToSaveChanged);
The last parameter is a callback function called when the registered property changes.
Automatic update of model's properties:
We set a property as a Model:
[Model]
public MyModel MyModel
{
get { return GetValue<MyModel>(MyModelProperty); }
set
{
_canGetDirty = false;
SetValue(MyModelProperty, value);
}
}
This class contains a few properties (Prop1, Prop2, Prop3). Catel allows us to automatically update them from the viewmodel by mapping them with ViewModelToModel:
[ViewModelToModel("MyModel")]
public string Prop1
{
get { return GetValue<string>(Prop1Property); }
set { SetValue(Prop1Property, value); }
}