绑定自动更新的属性

时间:2014-02-24 06:24:35

标签: c# properties

我没想到这会起作用,但我想尝试一下。我有一个bool应该告诉我用户是否在我的应用程序中选择了任何东西(在特定控件内)。

我想将某些内容绑定到那个bool:

        private bool _isAnythingSelected;
    public bool IsAnythingSelected
    {
        get
        {
            _isAnythingSelected = (MyModel.Series.Where(p => p.IsSelected && p.GetType() == typeof(LineSeries)).Count() > 0);
            return _isAnythingSelected;
        }
        set
        {
            _isAnythingSelected = value;
            RaisePropertyChanged("IsAnythingSelected");
        }
    }

这不符合我的意愿,我明白为什么会如此。我的问题是,如果不采用允许用户选择的每种方法,我应该如何实现这个选择?谢谢。

1 个答案:

答案 0 :(得分:1)

要正确更新IsAnythingSelected,您必须处理两种通知:

  • 有关MyModel.Series收集的通知已更改;
  • 关于MyModel.Series集合属性的通知已更改。

第一个可以通过ObservableCollection<T>(或任何其他实现INotifyCollectionChanged的集合“开箱即用”实现。
第二个需要一个自定义解决方案(至少,我不知道任何现有的“开箱即用”)。

您可以将ObservableCollection<T>与项目属性更改以这种方式结合使用:

class MyObservableCollection<T> : ObservableCollection<T>
    where T : INotifyPropertyChanged
{
    private void Initialize()
    {
        // initial PropertyChanged subscription
        foreach (var item in Items)
        {
            SubscribeItemPropertyChanged(item);
        }
    }

    private void SubscribeItemPropertyChanged(object item)
    {
        ((INotifyPropertyChanged)item).PropertyChanged += HandleItemPropertyChanged;
    }

    private void UnSubscribeItemPropertyChanged(object item)
    {
        ((INotifyPropertyChanged)item).PropertyChanged -= HandleItemPropertyChanged;
    }

    protected virtual void HandleItemPropertyChanged(object sender, PropertyChangedEventArgs args)
    {
        var handler = ItemPropertyChanged;
        if (handler != null)
        {
            handler(sender, args);
        }
    }

    protected override void ClearItems()
    {
        // we should unsubscribe from INotifyPropertyChanged.PropertyChanged event for each item
        Items.ToList().ForEach(item => Remove(item));
    }

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        base.OnCollectionChanged(e);

        // subscribe for new items property changing;
        // un-subscribe for old items property changing
        switch (e.Action)
        {
            case NotifyCollectionChangedAction.Add:
                SubscribeItemPropertyChanged(e.NewItems[0]);
                break;
            case NotifyCollectionChangedAction.Remove:
                UnSubscribeItemPropertyChanged(e.OldItems[0]);
                break;
            case NotifyCollectionChangedAction.Replace:
                SubscribeItemPropertyChanged(e.NewItems[0]);
                UnSubscribeItemPropertyChanged(e.OldItems[0]);
                break;
        }
    }

    public MyObservableCollection()
        : base()
    {
    }

    public MyObservableCollection(IEnumerable<T> collection)
        : base(collection)
    {
        Initialize();
    }

    public MyObservableCollection(List<T> list)
        : base(list)
    {
        Initialize();
    }

    public EventHandler<PropertyChangedEventArgs> ItemPropertyChanged;
}

...并使MyModel.Series成为MyObservableCollection<T>个实例 然后,您的包含IsAnythingSelected的类将如下所示:

// somewhere in code, where `MyModel` being initialized:
MyModel.Series.CollectionChanged += (sender, args) => RaisePropertyChanged("IsAnythingSelected");
MyModel.Series.ItemPropertyChanged += (sender, args) => RaisePropertyChanged("IsAnythingSelected");

    public bool IsAnythingSelected
    {
        get
        {
            return MyModel.Series.Any(p => p.IsSelected && p.GetType() == typeof(LineSeries));
        }
    }

在这种情况下,您甚至不需要IsAnythingSelected成为读写属性。只需通知,它已被更改,绑定引擎将重新读取其值。