为什么没有人使用INotifyPropertyChanging呢?

本文关键字:INotifyPropertyChanging 没有人 为什么 | 更新日期: 2023-09-27 18:13:37

我知道MVVM大量使用INotifyPropertyChanged,但我从未见过INotifyPropertyChanged的任何用法。有什么原因吗?

如果我确实想使用这个,将它集成到我的MVVM框架的好方法是什么?我知道你不应该在ViewModel上使用MessageBox,因为那样你就不能对它进行单元测试。那么,如何抛出一个警报,然后继续使用PropertyChange(如果适用)呢?

为什么没有人使用INotifyPropertyChanging呢?

关于INotifyPropertyChanging要记住的是你不能阻止变化的发生。这仅仅允许您记录发生的更改。

我在我的框架中使用它来跟踪更改,但它不是一个合适的停止更改的方法。

您可以使用自定义接口/事件对扩展您的ViewModelBase:

delegate void AcceptPendingChangeHandler(
    object sender,
    AcceptPendingChangeEventArgs e);
interface IAcceptPendingChange
{
    AcceptPendingChangeHandler PendingChange;
}
class AcceptPendingChangeEventArgs : EventArgs
{
    public string PropertyName { get; private set; }
    public object NewValue { get; private set; }
    public bool CancelPendingChange { get; set; }
    // flesh this puppy out
}
class ViewModelBase : IAcceptPendingChange, ...
{
    protected virtual bool RaiseAcceptPendingChange(
        string propertyName,
        object newValue)
    {
        var e = new AcceptPendingChangeEventArgs(propertyName, newValue)
        var handler = this.PendingChange;
        if (null != handler)
        {
            handler(this, e);
        }
        return !e.CancelPendingChange;
    }
}
此时,您需要按照约定将其添加到视图模型中:
class SomeViewModel : ViewModelBase
{
     public string Foo
     {
         get { return this.foo; }
         set
         {
             if (this.RaiseAcceptPendingChange("Foo", value))
             {
                 this.RaiseNotifyPropertyChanging("Foo");
                 this.foo = value;
                 this.RaiseNotifyPropretyChanged("Foo");
             }
         }
     }
}

INotifyPropertyChanging是用于Linq to SQL的优化。当一个对象实现这个接口时,它使用变化事件作为信号来缓存属性的旧值。如果对象没有实现这个接口,那么它将始终缓存属性值,从而增加内存使用。查看INotifyPropertyChanging接口如何帮助限制内存消耗了解更多细节。

要回答第二个问题,你总是可以使用依赖注入模式让你的VM依赖于一个接口(INotifier?),并传递一个弹出MessageBoxes的具体实现。这使得单元可测试性完好无损。

编辑:第一个问题对SO来说可能太主观了。接口的意图是明确的,但何时使用它将是非常具体的用例。依赖属性也会引发类似的问题,这对于在应用新值之前检查它是否有效很有用,但如果你使用的是简单的属性,那么你可以更简单地把这个检查放在setter中。如果一个不同的组件需要检查有效性,那么如果该组件自己进行更改(在验证新值之后),或者由进行更改的组件显式调用来验证更改,通常会更简单。

INotifyPropertyChanging在属性更改之前被调用。为什么重要?以便外部事件处理程序可以抛出异常并阻止更改。你为什么要这么做?有一天,它可能是您解决其他人代码库中的错误的唯一方法,所以不要这么快地删除逃生舱口。

你需要INotifyPropertyChanged例如,如果你想知道什么时候任何变量将被改变,因为你可以使用PropertyChangedEventHandler。通过这种方式,如果在任何gui元素上绑定了任何依赖属性,则可以在运行程序时重新加载gui。

对于最后一个问题,我认为你可以用你定义的消息写一个日志文件,如果你想向用户显示任何警报,你可以使用错误摘要或工具提示等控件。但是,如果您只需要用于测试,则可以使用try和catch块将警报保留在下面。