创建通用 ObservableItem Class

Creating a generic ObservableItem Class

我想创建一个通用的 ObservableItem class,我想了解如何实现它。 我希望它是通用的,这样我就可以将它用于所有类型的类型(如果可能的话)。 我想要创建它的原因是能够将多个控件绑定到一个数组,而不是为每个绑定创建属性。 (我想要双向绑定,以便在更新源时,将通过 PropertyChanged 事件通知控件)。 我开始创建 class,但我不知道要添加什么实现才能使其对每种类型都通用。

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;
    }
}

我希望 class 的用途应该适用于所有方面:

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>

提前致谢。

我找到了解决问题的方法,所以我将其作为答案发布给大家使用。

我没有找到一种方法来创建通用的 ObservableItem 以允许我将它用作每个对象。喜欢:

public ObservableItem<bool> value {get;set}

并在 xaml 中直接绑定到 'value' 而不是 'value.Item'。 此外,每当我使用隐式运算符更改值时,绑定就会停止。

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

所以,我写了一个ObservableItemCollection,它继承了ObservableCollection,并重新实现了ObservableCollection的indexer operator base the Collection,这样每次set操作都会调用PropertyChanged事件处理程序。

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));
    }
}

这样我就可以像使用任何 class 数组一样使用集合,并直接绑定到项目。

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>

>