【问题标题】:Bind to Collection Count Where绑定到集合计数在哪里
【发布时间】:2019-01-06 19:56:39
【问题描述】:

我的问题和这个类似:Bind to Count of List where Typeof

但这对类有什么作用呢?

在我的 MainWindow 中,我有以下 Collection 和 Selected Count 属性

private ObservableCollection<MyClass> _myClassCollection = new ObservableCollection<MyClass>();
public ObservableCollection<MyClass>
{
    get => _myClassCollection;
    set 
    {
        if(_myClassCollection == value) return;
        _myClassCollection = value;
        OnPropertyChanged("MyClassCollection");
    }
}

public int SelectedCount
{
    get => MyClassCollection.Where(x => x.IsSelected == true).Count();
}

public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

我的班级:

public class MyClass : INotifyPropertyChanged
{
    // .. Properties
    private bool _isSelected;
    public bool IsSelected
    {
        get => _isSelected;
        set
        {
            if(_isSelected == value) return;
            _isSelected = value;
            OnPropertyChanged("IsSelected");
        }
    }
}

public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

那么,如果MyClassIsSelected 属性发生了变化,我该如何“运行”SelectedCount 属性呢?我想实时显示 ObservableCollection 的 Selected Items 的数量。

【问题讨论】:

  • 顺便说一下,SelectedCount 的代码是 O(n)。在循环中的某个地方使用它,例如对于绑定(这将导致 O(n^2)),瞧,当您的收藏有大约 500 个项目时,您会看到 100% 的 cpu 核心。

标签: c# wpf


【解决方案1】:

您可以在可能发生更改的其他操作的设置器中为 SelectedCount 添加一个 OnPropertyChaned。例如设置我的班级集合。这将告诉监听该特定属性的东西可能已更改,再次获取该值。

set 
{
    if(_myClassCollection == value) return;
    _myClassCollection = value;
    OnPropertyChanged("MyClassCollection");
    OnPropertyChanged("SelectedCount");  // Make the change Here.
}

从 cmets 看来,您似乎需要明确地监听每个元素的属性更改。这是一个使用事件处理程序在您的 setter 中的外观示例。

set 
{
    // remove subscriptions
    if(_myClassCollection != null) 
    {
       foreach(var element in _myClassCollection)
       {
          element.PropertyChanged -= ElementChanged;
       } 
    }

     // set to new collection
    _myClassCollection = value;

    // subscribe to new elements.
    if(_myClassCollection != null) 
    {
       foreach(var element in _myClassCollection)
       {
          element.PropertyChanged += ElementChanged;
       } 
    }

    OnPropertyChanged("MyClassCollection");
    OnPropertyChanged("SelectedCount");  // Make the change Here.
}



private void ElementChanged(object sender, PropertyChangedEventArgs e)
{
    if(e.PropertyName == nameof(MyClass.IsSelected))
    {
         OnPropertyChanged("SelectedCount");
    }
}

现在,如果您要在集合中添加或删除元素而不创建新集合,则需要在 CollectionChanged 事件处理程序中订阅或删除订阅。

【讨论】:

  • 这不起作用。我猜是因为如果MyClass 上的属性IsSelected 被击中,MyClassCollectionPropertyChanged 将不会被击中。 MyClassIsSelected 属性绑定到 ComboBox.IsSelected。因此,如果我点击组合框来选择/取消选择它,只会点击 MyClass.IsSelected 的事件。
  • 您需要单独监听集合中所有 MyClass 对象的属性更改,并在执行时调用OnPropertyChanged
  • 但我无法从MyClass.IsSelected 调用OnPropertyChanged("SelectedCount")
  • 似乎仍然无法正常工作。我通过MyClassCollection.Add(new MyClass ....)将项目添加到集合中我现在应该以其他方式添加项目吗?
  • 您可以通过多种方式来完成这部分工作。在创建 MyClass 对象时,您可以直接订阅。或者开始收听MyClassCollection.CollectionChanged 事件并在那里订阅添加。 Example
【解决方案2】:

您可以使用DynamicData 使其更具可读性:

var allObjects = new SourceList<MyClass>(); // this is what you populate with your objects

SelectedObjects = allObjects.Connect().Filter(x => x.IsSelected).AsObservableList();

如果 SelectedObjects 是公共属性,您可以像这样绑定:

<TextBloc Text="{Binding SelectedObjects.Count}"/>

【讨论】:

    【解决方案3】:

    您必须处理来自您的ObservableCollectionCollectionChanged。 在那里,您必须像链接的问题一样致电OnPropertyChanged("SelectedCount")

    在你的集合中:

    _myClassCollection.CollectionChanged += Handle_CollectionChanged;
    

    在事件处理程序中:

    private void Handle_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        OnPropertyChanged("SelectedCount");
    }
    

    【讨论】:

    • 不起作用。我在if(_myClassCollection == value) return 上方设置了CollectionChanged += 行。我还更新了我的问题,为您提供更多信息。
    猜你喜欢
    • 2013-03-15
    • 2013-07-13
    • 1970-01-01
    • 2017-12-20
    • 2018-05-16
    • 2011-01-09
    • 2012-06-14
    • 2023-04-08
    • 1970-01-01
    相关资源
    最近更新 更多