【问题标题】:Silverlight & ObservableCollection: Raising CollectionChanged on UI threadSilverlight 和 ObservableCollection:在 UI 线程上引发 CollectionChanged
【发布时间】:2010-10-06 02:27:42
【问题描述】:

我需要在 UI 线程上引发 ObservableCollection 的 CollectionChanged 事件。

我见过不同的方法,从包装类到相关接口的自定义实现。

是否有任何简单的方法可以覆盖 ObservableCollection 上的 INotifyCollectionChanged 来完成此操作?

谢谢。

【问题讨论】:

    标签: silverlight observablecollection


    【解决方案1】:

    您可以继承 ObservableCollection 并覆盖 OnCollectionChanged 和 OnPropertyChanged 方法,以使用相应的 Dispatcher 将事件编组回 UI 线程。

    public class DispatcherObservableCollection<T> : ObservableCollection<T>
    {
        Dispatcher _dispatcher;
        public DispatcherObservableCollection(Dispatcher dispatcher)
        {
            if (dispatcher == null)
                throw new ArgumentNullException("dispatcher");
            _dispatcher = dispatcher;
        }
    
        protected override void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (!_dispatcher.CheckAccess())
            {
                _dispatcher.Invoke(
                    new Action<PropertyChangedEventArgs>(base.OnPropertyChanged), e);
            }
            else
            {
                base.OnPropertyChanged(e);
            }
        }
    
        protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            if (!_dispatcher.CheckAccess())
            {
                _dispatcher.Invoke(
                    new Action<NotifyCollectionChangedEventArgs>(base.OnCollectionChanged), e);
            }
            else
            {
                base.OnCollectionChanged(e);
            }
        }
    }
    

    【讨论】:

    • 非常好的主意。但是,它仅在将 Invoke 替换为 BeginInvoke 后才对我有用。
    【解决方案2】:

    执行此操作的最简单方法是确保您在 UI 线程上从集合中添加/删除项目。这可以通过这样的简短函数来完成:

    private void AddItemsToCollection(List<whatever> newItems)
    {
        if (this.Dispatcher.CheckAccess()) 
        {
            newItems.ForEach(x => myObservableCollection.Add(x));
        }
        else 
            this.Dispatcher.BeginInvoke(new Action<List<whatever>>(AddItemsToCollection), newItems);
    }
    

    【讨论】:

    • 谢谢,但我在后台有很多事情要做(比如异步加载操作等)。还有其他想法吗?
    • 我会给你的建议。
    • @Derick - 这就是该功能的美妙之处 - 无论您在哪个线程上调用它,它都会在更新之前将自己编组到 UI 线程(如果还没有的话) .
    • 看来我可以从火星上调用它,它仍然有效。谢谢老兄!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-12
    • 1970-01-01
    相关资源
    最近更新 更多