Wpf 延迟项的可见性控件项

Wpf 延迟项的可见性控件项,wpf,visibility,itemscontrol,deferred,Wpf,Visibility,Itemscontrol,Deferred,我有一个场景,其中我希望在ItemsControl中显示许多项。由于项目的布局方式(使用画布),我无法使用标准的虚拟化面板,因此加载控件需要很长时间 我想知道如何分批加载这些项目,而不是一次性加载所有项目 例如,如果我使用的是一个ListBox,它的itemsSource设置为某个大列表,我如何才能批量创建ListBoxItems,比如说10个项目,将剩余的延迟到下一个Dispatcher事件(后台或AppIdle)上运行 通过让ItemsSource成为一个可观察的集合,随着每个新批处理的增长

我有一个场景,其中我希望在ItemsControl中显示许多项。由于项目的布局方式(使用画布),我无法使用标准的虚拟化面板,因此加载控件需要很长时间

我想知道如何分批加载这些项目,而不是一次性加载所有项目

例如,如果我使用的是一个ListBox,它的itemsSource设置为某个大列表,我如何才能批量创建ListBoxItems,比如说10个项目,将剩余的延迟到下一个Dispatcher事件(后台或AppIdle)上运行

通过让ItemsSource成为一个可观察的集合,随着每个新批处理的增长,这个问题可以很容易地从ViewModel中解决,但是我想在视图级别添加它


我也不希望使用ItemContainers可见性属性来实现它,因为它很可能已经被使用了。

这将取决于数据来自何处。但我可以告诉你,从视图加载只是一个糟糕的计划

  • 将ItemsSource设置为ViewModel中的ObservableCollection
  • 从后台线程更新ObservableCollection,使其不会影响您的UI
  • 确保在更新时不重新实例化实例,而是清除并重新填充集合 我相信WPF现在允许对ObservableCollection进行跨线程更新。如果没有,您可以始终使用Caliburn这样的库,因为它是BindableCollection

    你也可以创建自己喜欢的

    守则:

    /// <summary>
    /// Initializes a new instance of the 
    /// <see cref="ObservableCollectionEx{T}"/> class.
    /// </summary> 
    public class ObservableCollectionEx<T> : ObservableCollection<T>
    {
        #region Constructors
    
        /// <summary>
        /// Initializes a new instance of the
        /// <see cref="ObservableCollectionEx{T}" /> class.
        /// </summary>
        public ObservableCollectionEx()
        {
        }
    
        ///
        /// Initializes a new instance of the
        ///  class.
        ///
        ///The collection.
        public ObservableCollectionEx(IEnumerable<T> collection) : this()
        {
            this.AddRange(collection);
        }
    
        #endregion
    
        #region Events
    
        /// <summary>
        /// Source: New Things I Learned
        /// Title: Have worker thread update ObservableCollection that is bound to a ListCollectionView
        /// http://geekswithblogs.net/NewThingsILearned/archive/2008/01/16/have-worker-thread-update-observablecollection-that-is-bound-to-a.aspx
        /// Note: Improved for clarity and the following of proper coding standards.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            // Use BlockReentrancy
            using (BlockReentrancy())
            {
                var eventHandler = CollectionChanged;
                if (eventHandler == null) return;
    
                // Only proceed if handler exists.
                Delegate[] delegates = eventHandler.GetInvocationList();
    
                // Walk through invocation list.
                foreach (var @delegate in delegates)
                {
                    var handler = (NotifyCollectionChangedEventHandler)@delegate;
                    var currentDispatcher = handler.Target as DispatcherObject;
    
                    // If the subscriber is a DispatcherObject and different thread.
                    if ((currentDispatcher != null) &amp;&amp; (!currentDispatcher.CheckAccess()))
                    {
                        // Invoke handler in the target dispatcher's thread.
                        currentDispatcher.Dispatcher.Invoke(
                            DispatcherPriority.DataBind, handler, this, e);
                    }
    
                    else
                    {
                        // Execute as-is
                        handler(this, e);
                    }
                }
            }
        }
    
        /// <summary>
        /// Overridden NotifyCollectionChangedEventHandler event.
        /// </summary>
        public override event NotifyCollectionChangedEventHandler CollectionChanged;
    
        #endregion
    }
    
    //
    ///初始化的新实例
    ///班级。
    ///  
    公共类ObservableCollectionEx:ObservableCollection
    {
    #区域构造函数
    /// 
    ///初始化的新实例
    ///班级。
    /// 
    公共可观测集合
    {
    }
    ///
    ///初始化的新实例
    ///班级。
    ///
    ///收藏。
    公共ObservableCollectionEx(IEnumerable集合):this()
    {
    此.AddRange(集合);
    }
    #端区
    #地区活动
    /// 
    ///资料来源:我学到的新东西
    ///标题:让工作线程更新绑定到ListCollectionView的ObservableCollection
    /// http://geekswithblogs.net/NewThingsILearned/archive/2008/01/16/have-worker-thread-update-observablecollection-that-is-bound-to-a.aspx
    ///注:为了清晰和遵循正确的编码标准而改进。
    /// 
    /// 
    CollectionChanged上的受保护覆盖无效(NotifyCollectionChangedEventArgs e)
    {
    //使用块重入
    使用(BlockReentrancy())
    {
    var eventHandler=CollectionChanged;
    if(eventHandler==null)返回;
    //仅当处理程序存在时才继续。
    Delegate[]delegates=eventHandler.GetInvocationList();
    //浏览调用列表。
    foreach(代理中的var@delegate)
    {
    var handler=(NotifyCollectionChangedEventHandler)@delegate;
    var currentDispatcher=handler.Target作为DispatcherObject;
    //如果订阅服务器是DispatcherObject和其他线程。
    if((currentDispatcher!=null)&;(!currentDispatcher.CheckAccess())
    {
    //在目标调度程序的线程中调用处理程序。
    currentDispatcher.Dispatcher.Invoke(
    DispatcherPriority.DataBind,handler,this,e);
    }
    其他的
    {
    //按原样执行
    处理者(本,e);
    }
    }
    }
    }
    /// 
    ///已重写NotifyCollectionChangedEventHandler事件。
    /// 
    公共覆盖事件NotifyCollectionChangedEventHandler CollectionChanged;
    #端区
    }
    
    正如我在问题中提到的,我知道我可以很容易地从ViewModel完成这项工作。