2012-08-16 15 views
0

我遇到了一個問題,我在DataModelViewModelPropertyChanged event之間無限循環。如何爲INotifyPropertyChanged接口創建自己的PropertyChangedEventArgs?

我的結構:

public class SomeDataModel : DataModelBase 
{ 
    public SomeDataModel() 
    { 

    } 

    public object SomeProperty 
    { 
     get 
     { 
      // 
     } 
     set; 
     { 
      // 
      OnPropertyChanged("SomeProperty"); 
     } 
    } 

    public bool SomeMethod() 
    { 
     SomeProperty = SomeNewObject 
    } 
} 

public class SomeViewModel : ViewModelBase 
{ 
    public SomeViewModel() 
    { 

    } 

    public SomeDataModel SomeDataModel 
    { 
     get; 
     set; 
    } 

    public object SomeProperty 
    { 
     get 
     { 
      return SomeDataModel.SomeProperty; 
     } 
     set 
     { 
      SomeDataModel.SomeProperty = value; 
      OnPropertyChanged("SomeProperty"); 
     } 
    } 
} 

兩個ViewModelDataModel實現INotifyPropertyChanged

然後我在我的ViewModelBase一個listener的,在我的DataModel改變任何property

private void DataModel_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    PropertyInfo toPropertyInfo = this.GetType().GetProperty(e.PropertyName); 
    PropertyInfo fromPropertyInfo = DataModel.GetType().GetProperty(e.PropertyName); 

    if (toPropertyInfo != null && fromPropertyInfo != null) 
    { 
     if (toPropertyInfo.CanWrite && fromPropertyInfo.CanRead) 
     { 
      toPropertyInfo.SetValue(this, fromPropertyInfo.GetValue(DataModel, null), null); 
     } 
    } 
} 

property被設定所以現在在DataModel,聽者ViewModelBase漁獲物,並更新相關propertyViewModel。但ViewModel中的設置將其重新設置爲DataModel,原因OnPropertyChanged("SomeProperty");會觸發agian,並以無限循環結束。

  1. 是否有快速解決問題的方法? (注意:無法更改結構)
  2. 我能夠創建自己的自定義類,從PropertyChangedEventArgs繼承,並仍然有我的INotifyPropertyChanged操作工作?

我在想:

public class CustomPropertyChangedEventArgs : PropertyChangedEventArgs 
{ 
    public CustomPropertyChangedEventArgs(string propertyName, SomeEnum enumName) 
     : base(propertyName) 
    { 
     //Set enum 
    } 
} 

,然後在OnPropertyChanged我想使用新的CustomPropertyChangedEventArgs並傳入我想使用enum

public void OnPropertyChanged(string propertyName) 
{ 
    CustomPropertyChangedEventArgs handler = this.PropertyChanged; 

    if (handler != null) 
    { 
     handler(this, new CustomPropertyChangedEventArgs(propertyName, newEnum)); 
    } 
} 
+0

我可能會得到抨擊,但我把在每個對象(檢查並添加進入的方法,並刪除在退出方法)目前正在發生變化的所有屬性名的一流水平列表。如果當我輸入OnPropertyChanged時,屬性名稱已經在列表中,我只是返回而不做任何事情。我寧願不刷新,也不願冒着無限循環的風險。 – Belmiris 2012-08-16 15:49:51

+0

是的,我會在代碼審查中爆炸你。 :) – tsells 2012-08-16 16:37:50

+0

只要您確定沒有人會調用OnPropertyChanged但屬性集代碼,Amiram Korach就有最好的方法。否則將永遠存在無限循環的風險。我會對憤怒的用戶和崩潰的程序進行差評=) – Belmiris 2012-08-16 16:47:32

回答

4

您可以檢查值是否相同並且不更新它。這通常是INotifyPropertyChanged實施。只有在確實更改後,纔會觸發OnPropertyChanged

public object SomeProperty 
{ 
    get 
    { 
     return SomeDataModel.SomeProperty; 
    } 
    set 
    { 
     if (SomeDataModel.SomeProperty != value) 
     { 
      SomeDataModel.SomeProperty = value; 
      OnPropertyChanged("SomeProperty"); 
     } 
    } 
} 
+0

這是完美的。不能相信我錯過了這種方式。謝謝:) – Willem 2012-08-16 17:32:47

0
you can disable and enable the event to avoid loop 
private void DataModel_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    OnPropertyChanged -= DataModel_PropertyChanged; 
    PropertyInfo toPropertyInfo = this.GetType().GetProperty(e.PropertyName); 
    PropertyInfo fromPropertyInfo = DataModel.GetType().GetProperty(e.PropertyName); 

    if (toPropertyInfo != null && fromPropertyInfo != null) 
    { 
     if (toPropertyInfo.CanWrite && fromPropertyInfo.CanRead) 
     { 
      toPropertyInfo.SetValue(this, fromPropertyInfo.GetValue(DataModel, null), null); 
     } 
    } 
    OnPropertyChanged += DataModel_PropertyChanged; 
} 
+1

我也會避免這一點。如果您的模型/視圖模型設置正確,應該沒有理由。 – tsells 2012-08-16 16:39:07

+0

它不是線程安全的,除非你真的不知道該怎麼做這是你可以嘗試的最後一件事。 – Larry 2012-09-14 14:21:26