2013-04-17 37 views
2

让我们假设属性Name在这个视图中绑定到TextBox。WPF框架如何处理MVVM中属性的循环更新?

private string name 
public string Name 
{ 
    get {return name;} 
    set { 
     name=value; 
     OnPropertyChanged("Name"); 
    } 
} 

查看

<TextBox Text="{Binding Name, Mode=TwoWay"/> 

当我们更新文本框中的文本,它会调用的名称属性的setter这反过来又提高的PropertyChanged这些假设再次更新UI。我很好奇WPF如何避免更新和提升事件的递归。是通过考虑该事件的发件人完成的?

回答

0

据我所知,没有递归。

1)TextBox使用viewmodel属性更新值。

2)视图模型提出了更新,让UI知道,事情发生了转变

3)文本框现在可以更新自己相匹配的视图模型值。

+2

4)TextBox使用viewmodel属性更新值... –

+0

没有第四步。这是不需要的,因为在第一步中,TextBox已经具有新的值(内部存储),并且它不会“重新触发”两次同样的更新到viewmodel。它有简单的检查到位。这就是为什么你有时需要做“var x = Property; Property = null; Property = x;”到“重新触发”绑定机制,因为它在内部存储了相同的值。 (例如,Property = _samePropertyValue不会将其切割) –

+0

不,这就是为什么您应该检查setter本身内部实际更改的属性值。您不需要在自己的代码中处理错误的PropertyChanged通知,只需使通知正确无误。我也会注意到你在答案中没有提到任何这一点。根据你自己的描述,肯定有无限递归。 –

3

的标准实现的属性应该是这样的:

private string name; 

public string Name 
{ 
    get { return name; } 

    set 
    { 
     if(name != value) 
     { 
      name = value; 
      OnPropertyChanged("Name"); 
     } 
    } 
} 

注意额外if以确保该事件只是提出如果属性的值实际上改变。

+0

我认为你不需要这个,因为OnPropertyChanged在内部检测新值是否不同。 – Vale

+1

OnPropertChanged不是.NET函数。所以如果你在*你的应用程序中这样写的话,那么你是对的。但是这样做完全没有效率,因为它必须使用反射才能获得您之前已知的属性。 – nvoigt

+0

是的,但我假设它在内部调用PropertyChanged(this,new PropertyChangedEventArgs(“Name”)) – Vale

0

可以从here的答案帮助你。

如果你从UI设置属性viewmodel它是这样的。

  • 二传手通话开始
  • 值设置
  • INotifyPropertyChanged的开始
  • INotifyPropertyChanged的做
  • 二传手做
  • 吸叫,做
  • IDataErrorInfo的叫,做

,但如果你在你的视图模型设置属性它是这样的

  • 二传手通话开始
  • 值设置
  • INotifyPropertyChanged的开始
  • 吸叫,做
  • IDataErrorInfo的叫,做
  • INotifyPropertyChanged完成
  • 执行器完成

从UI到视图模型更改属性可能导致死锁那种 情况可能有两种方式 场景运行到年末减少递归调用。为了阻止这种情况发生,当WPF将 更改为模型时,它将继续通过 INotifyPropertyChanged跟踪更改,但此更改将在调度程序 队列中排队,并且将在其当前更新完成后执行。

由于viewmodel的更改不是由WPF启动的,因此WPF不会在 的队列中执行操作,它会立即执行更改。

+0

谢谢,是的,你有我的问题,但解释不清楚。 “当WPF正在对模型进行更改时,它将通过INotifyPropertyChanged继续跟踪更改,但此更改将在调度程序队列中排队,并且将在其当前更新完成后执行”。我感觉到的是,当它处理这些排队的项目时,它会再次引发事件并继续无限循环。它在框架中如何处理? – dev8516