我正在尝试用Catel制作一个“Dirty”实现。
我有一个viewmodel,其[Model]
属性和一些[ViewModelToModel]
映射到它
我添加了一个布尔成员_canGetDirty
,当设置为true
时,允许viewmodel属性提示服务进行保存。
所以我的逻辑是,如果模型属性发生更改,_canGetDirty
将设置为false
,因此viewmodel属性会更改而不会变脏,并且当模型完成更改时,我们设置{{1} } _canGetDirty
重新开始。
问题是在更改viewmodel属性之前调用了model属性的true
事件,因此PropertyChanged
始终为true,并且每当我加载新模型时都会调用我的服务进行保存
如何解决此问题?
_canGetDirty
编辑:关于Catel如何在此背景下工作的一些解释。
我们注册的属性会通过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
}
通知更新:
RegisterProperty
最后一个参数是注册属性更改时调用的回调函数。
我们将属性设置为模型:
public static readonly PropertyData Prop1Property = RegisterProperty("Prop1",
typeof(string), null, PropertyToSaveChanged);
此类包含一些属性(Prop1,Prop2,Prop3)。 Catel允许我们通过使用ViewModelToModel映射它们来自viewmodel自动更新它们:
[Model]
public MyModel MyModel
{
get { return GetValue<MyModel>(MyModelProperty); }
set
{
_canGetDirty = false;
SetValue(MyModelProperty, value);
}
}
答案 0 :(得分:1)
首先,我建议使用Catel.Fody,这会大大简化您的财产注册(是的,它还支持更改回调;-))。
为什么模型会从外部改变?当模型发生变化(它被注入你的ctor)时,它应该重新创建一个新的VM,因此你可以从一个新的平板开始。
回到这个问题:你测试过你的二传手是否真的被调用了吗?有可能Catel内部直接调用SetValue(等于依赖属性的行为),而不是调用vm中的包装器。 Catel以这种方式工作:
我怀疑你基本上是在设置_canBeDirty =&gt;太早了。
答案 1 :(得分:0)
假设ViewModelBase
遵守INotifyPropertyChanged
订阅类&#39; INotifyPropertyChanged
事件并在其中设置脏标志,而不是订阅单个更改事件。
根据定义,应该在设置任何值之后发生。
示例
public MyViewModel(MyModel myModel, IMyService myService)
{
...
this.PropertyChanged += (sender, args) =>
{
if (_canGetDirty)
_myService?.AskForSaving();
};
}
您可以使用args.PropertyName
检查清除模式中的任何竞争条件逻辑。