我正在使用带有MVVM模式的WPF。
在我的模型类中,我使用从PropertyChangingEventArgs派生的自定义EventArgs实现INotifyPropertyChanging接口。这是必要的,因为我希望能够“取消”属性设置器。
此事件正在包含该模型的ViewModel中处理。
在事件处理程序中,我必须调用数据库并根据结果有时我必须通过事件args取消属性设置器。
该模型看起来类似于以下内容:
public class CancellablePropertyChangingEventArgs : PropertyChangingEventArgs
{
public bool Cancel { get; set; }
}
public class Model : INotifyPropertyChanging
{
public string MyProperty
{
get { return _myProperty; }
set
{
var args = RaisePropertyChanging();
if(!args.Cancel)
_myProperty = value;
}
}
public CancellablePropertyChangingEventArgs RaisePropertyChanging([CallerMemberName] string propertyName = "")
{
var eventArgs = new CancellablePropertyChangingEventArgs(propertyName);
if(PropertyChanging != null)
{
PropertyChanging(this, eventArgs);
}
return eventArgs;
}
}
包含上述模型并处理PropertyChanging事件的viewmodel,在事件处理程序中我有一个类似于此的代码:
private async void HandleModelPropertyChanging(object sender, PropertyChangingEventArgs e)
{
var args = e as CancellablePropertyChangingEventArgs;
if(args.PropertyName = "MyProperty")
{
var result = await CallToDataBaseAsync(...);
if(result == null)
args.Cancel = true;
}
}
我知道事件处理程序中的async void意味着“Fire and Forget”,因此事件处理程序继续在CallToDataBaseAsync执行而不是等待它,因此args.Cancel将始终为false。
但是,在没有阻止GUI-Thread的情况下,我可以尝试其他任何可能的解决方案吗?
答案 0 :(得分:3)
我之前确实走过这条路 - 取消制定者是错误的做法,它不会像你期望的那样工作,即使等待着。设置此属性的wpf绑定要求您更改属性或将异常作为验证机制。如此简单的取消通过不分配值而不是触发PropertyChanged
事件将导致设置此属性的控件的不同步 - 它将显示由用户键入的数据,而不是实际存储在属性中的数据。
如果你真的想尝试它,无论如何都要改变你的处理程序以返回任务,但要记住这是有缺陷的解决方案 - 如果你有多个处理程序附加只有最后一个的结果将等待。通过一些更多的工作,你可以聚合这些任务,但无论如何都是毫无意义的。