2011-09-30 43 views
0

我有一個類ViewModel,它具有類型爲BindingList<Foo>的屬性MyList當BindingList元素的屬性發生變化時丟失PropertyChanged事件

ViewModel implements INotifyPropertyChanged

Foo的財產FooProp

Foo實現INotifyPropertyChanged

視圖模型具有這個屬性:

public bool IsButtonEnabled 
    { 
    get 
    { 
     return MyList.Any(x=> x.FooProp!=null); 
    } 
} 

我有一個按鈕,一個視圖。該按鈕的Enabled屬性綁定到IsButtonEnabled

但是,當MyList的元素已設置爲FooProp時,該按鈕不會啓用。我注意到ViewModel在這裏不會觸發PropertyChanged事件。爲什麼不?我應該如何去查看模型,注意到它的屬性實際上已經改變了?

+0

你可以發佈剩下的代碼嗎?是否所有FooProps都不是null或只有一個? –

回答

0

編輯:沒有注意到,這是一個吸氣,而不是一個二傳手。這一點仍然是一樣的。只需實現INotifyPropertyChanged接口不會自動添加所需的所有內容。您需要創建觸發事件的方法(下圖)。然後您需要在所有屬性的SETTER中調用該方法。

你不應該自己觸發PropertyChanged事件嗎?

public bool IsButtonEnabled 
{ 
    get 
    { 
     return MyList.Any(x=> x.FooProp!=null); 

     // assuming you named the method this 
     OnPropertyChanged("IsButtonEnabled"); 
    } 
} 

INotifyPropertyChanged接口只會爲您創建事件。你需要自己從ViewModel中激發事件。

如果您尚未創建該方法,則通常可以使用該方法。當ViewModel的屬性發生變化時,您將顯式調用此方法。

private void OnPropertyChanged(string propertyName) 
{ 
    var handler = PropertyChanged; 
    if (handler != null) 
     PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
} 
+1

在那個吸氣者中引發事件沒有任何意義;) – Jefim

+0

你是對的。甚至沒有注意到它是一個吸氣而不是二傳手。 –

0

ViewModel在這裏不會觸發任何PropertyChanged,因爲ViewModel的屬性沒有改變。實際屬性被更改爲FooProp,這是Foo類的屬性,而不是ViewModel。

爲了啓用/禁用基於IsButtonEnabled功能的按鈕,您將必須跟蹤MyList的所有元素並查看是否有任何更改已完成。因此,下面應該工作:

public class Foo : INotifyPropertyChanged 
{ 
    void OnPropertyChanged(string propertyName) { /* ... */ } 
    public object FooProp 
    { 
     get { return _obj; } 
     set 
     { 
      _obj = value; 
      OnPropertyChanged("FooProp"); 
     } 
    } 
} 

public class ViewModel : INotifyPropertyChanged 
{ 
    void OnPropertyChanged(string propertyName) { /* ... */ } 

    private List<Foo> _myList; 
    public List<Foo> MyList 
    { 
     get { return _myList; } 
     set 
     { 
      _myList = value; 
      foreach(var item in _myList) 
      { 
       HandleItem(item); 
      } 
     } 
    } 

    void AddItem(Foo item) 
    { 
     MyList.Add(item); 
     HandleItem(item); 
    } 
    void HandleItem(Foo item) 
    { 
     item.PropertyChanged += (s, e) => 
     { 
      if(e.PropertyName == "FooProp") 
     }; 
    } 
    void ItemPropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     if(e.PropertyName == "FooProp") OnPropertyChanged("IsButtonEnabled"); 
    } 
    public bool IsButtonEnabled 
    { 
     get 
     { 
      return MyList.Any(x=> x.FooProp!=null); 
     } 
    } 
} 

注意,在這種情況下,你需要使用ViewModel.AddItem()以將項目添加到MYLIST(你可以使用MyList.Add(),但它不會然後發出正確的通知)。

此外,上面的代碼不是最好的方式來做到這一點 - 它只是你的情況應該如何工作的例證。在您瞭解到您可能會將列表<>替換爲ObservableCollection <>以便能夠自動跟蹤/處理列表中的項目。

相關問題