我知道MVVM大量使用INotifyPropertyChanged,但我从未见过INotifyPropertyChanging的任何用法。任何理由?为什么没有人使用INotifyPropertyChanging?
如果我想用这个,这将是该融入我的MVVM框架的好办法?我知道你不应该在ViewModel上使用MessageBox
,因为那样你就无法对它进行单元测试。那么如何才能抛出警报,然后继续使用PropertyChange(如果适用)?
我知道MVVM大量使用INotifyPropertyChanged,但我从未见过INotifyPropertyChanging的任何用法。任何理由?为什么没有人使用INotifyPropertyChanging?
如果我想用这个,这将是该融入我的MVVM框架的好办法?我知道你不应该在ViewModel上使用MessageBox
,因为那样你就无法对它进行单元测试。那么如何才能抛出警报,然后继续使用PropertyChange(如果适用)?
需要记住的事项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");
}
}
}
}
要回答第二个问题,你总是可以使用依赖注入模式,让您的虚拟机依赖的接口(INotifier?)上,并通过一个具体的实施会弹出消息框。这使单元测试性保持不变。
编辑: 第一个问题可能是这么过于主观。界面的意图很明确,但何时使用它将用于非常具体的用例。依赖属性引发了类似的情况,在应用它之前检查新值是有效的,但如果使用简单属性,则可以更简单地将此检查放入设置器中。如果不同的组件需要检查有效性,那么如果该组件自己(在验证新值之后)进行更改,或者被显式调用以验证由进行更改的组件进行的更改,则通常会更简单。
您需要INotifyPropertyChanged例如,如果你想知道什么时候任何变量将被改变,因为你可以使用PropertyChangedEventHandler。 通过这种方式,您可以在运行程序时重新加载gui,如果有任何依赖属性绑定在任何gui元素上。
对于最后一个问题,我想你可以写一个日志文件与你定义的消息,如果你想显示给用户的任何警报,您可以使用类似的错误总结或提示控件。但是,如果您只需要进行测试,则可以使用try和catch块保留警报。
OP询问'INotifyPropertyChanging'接口,而不是'INotifyPropertyChanged' –
忽略错误接口的无辜错误,在本场景中钻入日志文件并尝试/捕获不存在的属性验证异常不是很好的建议。 – JRoughan
INotifyPropertyChanging在属性更改之前被调用。重要原因?所以外部事件处理程序可以抛出异常并阻止更改。你为什么要这么做?有一天它可能是你在别人的代码库中的一个错误的唯一解决方法,所以不要那么快地删除逃生舱口。
在事件处理程序中抛出一个异常来结束事件执行时,firer会引起我的巨大代码嗅觉,包括执行此操作的选项*以防万一使我感觉更糟。 –
INotifyPropertyChanging是使用LINQ到使用SQL优化。当一个对象实现这个接口时,它使用改变事件作为缓存属性的旧值的信号。如果对象没有实现这个接口,那么它总是会缓存属性值,从而增加内存使用量。 有关更多详细信息,请参阅How does INotifyPropertyChanging interface helps limit memory consumption。
你想在这里实现什么?知道什么时候房产是*关于*改变的用例是什么? – ChrisF
验证用户“你确定吗?”对于某些更改......我们希望确保管理员意味着更改用户的用户名/登录名,并且他们不会意外更新该字段。 – michael