2011-11-03 34 views
12

我知道MVVM大量使用INotifyPropertyChanged,但我从未见过INotifyPropertyChanging的任何用法。任何理由?为什么没有人使用INotifyPropertyChanging?

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

+1

你想在这里实现什么?知道什么时候房产是*关于*改变的用例是什么? – ChrisF

+0

验证用户“你确定吗?”对于某些更改......我们希望确保管理员意味着更改用户的用户名/登录名,并且他们不会意外更新该字段。 – michael

回答

11

需要记住的事项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"); 
      } 
     } 
    } 
} 
1

要回答第二个问题,你总是可以使用依赖注入模式,让您的虚拟机依赖的接口(INotifier?)上,并通过一个具体的实施会弹出消息框。这使单元测试性保持不变。

编辑: 第一个问题可能是这么过于主观。界面的意图很明确,但何时使用它将用于非常具体的用例。依赖属性引发了类似的情况,在应用它之前检查新值是有效的,但如果使用简单属性,则可以更简单地将此检查放入设置器中。如果不同的组件需要检查有效性,那么如果该组件自己(在验证新值之后)进行更改,或者被显式调用以验证由进行更改的组件进行的更改,则通常会更简单。

-6

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

对于最后一个问题,我想你可以写一个日志文件与你定义的消息,如果你想显示给用户的任何警报,您可以使用类似的错误总结或提示控件。但是,如果您只需要进行测试,则可以使用try和catch块保留警报。

+1

OP询问'INotifyPropertyChanging'接口,而不是'INotifyPropertyChanged' –

+1

忽略错误接口的无辜错误,在本场景中钻入日志文件并尝试/捕获不存在的属性验证异常不是很好的建议。 – JRoughan

1

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

+5

在事件处理程序中抛出一个异常来结束事件执行时,firer会引起我的巨大代码嗅觉,包括执行此操作的选项*以防万一使我感觉更糟。 –

3

INotifyPropertyChanging是使用LINQ到使用SQL优化。当一个对象实现这个接口时,它使用改变事件作为缓存属性的旧值的信号。如果对象没有实现这个接口,那么它总是会缓存属性值,从而增加内存使用量。 有关更多详细信息,请参阅How does INotifyPropertyChanging interface helps limit memory consumption

相关问题