暂停绑定的ObservableCollection<T>数据网格更新

4
有没有办法暂停ObservableCollectionNotifyCollectionChanged事件?我想到了以下方式:
public class PausibleObservableCollection<Message> : ObservableCollection<Message>
{
    public bool IsBindingPaused { get; set; }

    protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (!IsBindingPaused)
            base.OnCollectionChanged(e);
    }
}

这确实暂停了通知,但显然被留下(但仍被添加)的项目在NotifyCollectionChangedEventArgs中,因此当我重新启用通知时,它们不会传递给绑定的DataGrid。

我需要自定义一个集合实现来控制这个方面吗?

2个回答

5
如果您不想错过任何通知,则可以采用临时存储,以下方法可能适用,但未经测试:
public class PausibleObservableCollection<T> : ObservableCollection<T>
{
    private readonly Queue<NotifyCollectionChangedEventArgs> _notificationQueue
        = new Queue<NotifyCollectionChangedEventArgs>();

    private bool _isBindingPaused = false;
    public bool IsBindingPaused
    {
        get { return _isBindingPaused; }
        set
        {
            _isBindingPaused = value;
            if (value == false)
            {
                while (_notificationQueue.Count > 0)
                {
                    OnCollectionChanged(_notificationQueue.Dequeue());
                }
            }
        }
    }

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (!IsBindingPaused)
            base.OnCollectionChanged(e);
        else
            _notificationQueue.Enqueue(e);
    }
}

在集合暂停期间发生的每个更改都应被推送到队列中,然后在集合被设置为恢复时将其清空。


看起来是一种很有前途且清晰的方法。我会尝试并告诉你它的效果如何... - rdoubleui
运行得很好,正如建议的那样,我更喜欢这种方法,因为我的DataGrid中将有几千个项目。简单而有效。 - rdoubleui

1
跟随 @H.B 的回答(我在他/她发布时正在测试) - 您可以将 NotifyCollectionChangedAction.Reset 更改操作作为事件参数传递给 CollectionChanged 事件。请注意,这对于大型集合来说效率不高。
public class PausibleObservableCollection<T> : ObservableCollection<T>
{
    private bool _isPaused = false;
    public bool IsPaused 
    { 
      get { return _isPaused; } 
      set 
      { 
          _isPaused = value;
          if (!value)
          { this.OnCollectionChanged(new System.Collections.Specialized.NotifyCollectionChangedEventArgs(System.Collections.Specialized.NotifyCollectionChangedAction.Reset)); }

      } 
    }

    protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (!IsPaused)
        { base.OnCollectionChanged(e); }
    }
}

我尝试了这个,按预期工作。但是,我的 DataGrid 中将有几千个项。根据我的阅读,NotifyCollectionChangedAction.Reset 基本上告诉 Grid 绑定所有项 - 因此您关于性能的提示非常关键。但很高兴知道有这样的选项。 - rdoubleui

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接