2015-03-02 67 views
0

我想創建一個通用的ObservableItem類,我想了解如何實現它。 我希望它是通用的,以便我可以使用它與所有類型的類型(如果可能的話)。 我想要創建它的原因是能夠將多個控件綁定到數組,而不是爲每個綁定創建屬性。 (我想要一個雙向綁定,以便當源更新時,控件將通過PropertyChanged事件通知)。 我開始創建類,但我不知道要添加什麼實現才能使其對於每種類型的用途都是通用的。創建一個通用的ObservableItem類

public struct ObservableItem<T> : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    private T _item; 
    private T Item 
    { 
     get { 

      return _item; 
     } 
     set 
     { 
      _item = value; 
      var handler = PropertyChanged; 
      if (handler != null) 
       handler(this, new PropertyChangedEventArgs(_item.ToString())); 
     } 
    } 


    public static implicit operator T(ObservableItem<T> value) 
    { 
     return value.Item; 
    } 

    public static implicit operator ObservableItem<T>(T value) 
    { 
     var ret = new ObservableItem<T>(); 
     ret.Item = value; 
     return ret; 
    } 
} 

我想用來與假設是適用於一切類:

ObservableItem<int> value1 = 5; 
ObservableItem<int>[] aValue = new ObservableItem<int>[5]; 
aValue[0] = 4; 
aValue[1] = 5; 
aValue[2] = aValue[0] + aValue[1]; 
aValue[3] = aValue[0] * aValue[1]; 

ObservableItem<bool> value2; 
value2 = !value2; 

ObservableItem<bool>[] Channels = new ObservableItem<bool>[4]; 
// and more uses 

XAML綁定:提前

<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0,0,0,10"> 
     <CheckBox IsChecked="{Binding Channels[0]}" Content="Channel 1" Style="{StaticResource Channels}"></CheckBox> 
     <CheckBox IsChecked="{Binding Channels[1]}" Content="Channel 2" Style="{StaticResource Channels}"></CheckBox> 
     <CheckBox IsChecked="{Binding Channels[2]}" Content="Channel 3" Style="{StaticResource Channels}"></CheckBox> 
     <CheckBox IsChecked="{Binding Channels[3]}" Content="Channel 4" Style="{StaticResource Channels}"></CheckBox> 
</StackPanel> 

感謝。

+1

'PropertyChanged'必須通過物業吶,E。 – SLaks 2015-03-02 19:17:44

+0

由於SLak錯過了5分鐘的編輯窗口:必須通過屬性*名稱*傳遞'PropertyChanged'。 – 2015-03-02 19:27:17

+0

'if(_item == null)_item = default(T);'行沒有意義。如果'T'是一個值類型,那麼'_item == null'將是錯誤的。如果'T'是一個引用類型,那麼'default(T)'將是'null'。 – juharr 2015-03-02 19:32:23

回答

0

我找到了一種解決我的問題的方法,所以我發佈它作爲每個人使用的答案。

我沒有找到一種方法來創建一個通用的ObservableItem,它允許我將它用作每個對象。像:

public ObservableItem<bool> value {get;set} 

而在XAML直接綁定到 '值',而不是 'value.Item'。 此外,無論何時我會用隱式運算符更改值,綁定都會停止。

value = !value; //kills the binding - because the object is replaced 

所以,我寫了繼承的ObservableCollection並重新實現的ObservableCollection的基地集合的索引操作,使每一套操作將調用PropertyChanged事件處理程序的ObservableItemCollection。

public class ObservableItemCollection<T> : ObservableCollection<T> 
{ 
    private string propertyName; 

    public ObservableItemCollection(string propertyName, int numberOfDefaultItemsToAdd = 0) 
     : base() 
    { 
     this.propertyName = propertyName; 
     this.AddDefaults(numberOfDefaultItemsToAdd); 
    } 
    public ObservableItemCollection(IEnumerable<T> collection, string propertyName, int numberOfDefaultItemsToAdd = 0) 
     : base(collection) 
    { 
     this.propertyName = propertyName; 
     this.AddDefaults(numberOfDefaultItemsToAdd); 
    } 
    public ObservableItemCollection(List<T> list, string propertyName, int numberOfDefaultItemsToAdd = 0) 
     : base(list) 
    { 
     this.propertyName = propertyName; 
     this.AddDefaults(numberOfDefaultItemsToAdd); 
    } 


    public new T this[int index] 
    { 
     get { return base[index]; } 
     set 
     { 
      base[index] = value; 
      // Call ObservableCollection OnPropertyChanged method. 
      OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    public void AddDefaults(int numberOfDefaultItemsToAdd = 1) 
    { 
     if (numberOfDefaultItemsToAdd < 0) throw new ArgumentOutOfRangeException("numberOfItemsToAdd must be a non-negative number"); 
     for(int i = 0; i < numberOfDefaultItemsToAdd; ++i) 
      base.Add(default(T)); 
    } 
} 

這樣我可以像任何類數組一樣使用集合,並直接綁定到該項目。

public ObservableItemCollection<bool> Channels { get; set; } 

而且在XAML:

<StackPanel Orientation="Horizontal" VerticalAlignment="Top"> 
    <CheckBox Content="Channel 1" IsChecked="{Binding Path=Channels[0]}" Style="{StaticResource Channels}"></CheckBox> 
    <CheckBox Content="Channel 2" IsChecked="{Binding Path=Channels[1]}" Style="{StaticResource Channels}"></CheckBox> 
</StackPanel> 

>