c# - 带有可取消 EventArgs 的 INotifyPropertyChanging EventHandler 中的异步/等待

标签 c# wpf mvvm asynchronous async-await

我正在使用带有 MVVM 模式的 WPF。

在我的模型类中,我使用派生自 PropertyChangingEventArgs 的自定义 EventArgs 实现了 INotifyPropertyChanging 接口(interface)。这是必要的,因为我希望能够“取消”属性 setter 。

此事件正在包含该模型的 ViewModel 中处理。

在事件处理程序中,我必须调用数据库并根据结果有时我必须通过事件参数取消属性 setter 。

该模型类似于以下内容:

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 事件的 View 模型,在事件处理程序中我有一个类似于此的代码:

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 表示“一劳永逸”,因此事件处理程序继续在 CallToDataBaseAsync 处执行而不是等待它,因此 args.Cancel 将始终为假。

但是,在不阻塞 GUI 线程的情况下,我可以尝试其他任何可能的解决方案吗?

最佳答案

我以前确实走过这条路-取消 setter 是错误的方法,即使在等待中,它也不会像您期望的那样工作。设置此属性的 wpf 绑定(bind)希望您更改该属性或抛出异常作为验证机制。如此简单的取消,不赋值也不触发PropertyChanged事件将导致设置此属性的控件不同步-它将显示用户键入的数据,而不是实际存储在属性中的数据。

如果您真的想尝试它,请将您的处理程序更改为返回 Task 但请记住这是有缺陷的解决方案 - 如果您要附加多个处理程序,则只会等待最后一个处理程序的结果。通过更多的工作,您可以汇总这些任务,但无论如何都是毫无意义的。

关于c# - 带有可取消 EventArgs 的 INotifyPropertyChanging EventHandler 中的异步/等待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19418592/

相关文章:

c# - 从枚举自动生成 DataGrid 列

Silverlight MVVM 绑定(bind)似乎不起作用

c# - 从 DataContext 获取值到 MarkupExtension

c# - ExecuteDataSet 超时发生在非常快的存储过程上

c# - 小数点后 3 位的 Math.Round 数

c# - 如何在代码隐藏中绑定(bind)到 Canvas.Left 或 Canvas.Top 附加属性?

c# - 使用 MVVM 时如何从 ViewModel 中访问 View 成员?

c# - 匿名并行任务计时器?

wpf - 从 cs 文件更改 Z 索引 wpf Canvas 元素

wpf - 如何将 Shell 中的按钮绑定(bind)到已加载模块的 View 模型中定义的命令?