2014-10-26 3 views
0

У меня есть сценарий, в котором я хочу представить множество элементов в ItemsControl. Из-за того, как элементы укладываются (используя холст), я не могу использовать стандартные панели виртуализации, поэтому для загрузки элемента управления требуется много времени.Отложить видимость элементов ItemsControl

Вместо того, чтобы нести время загрузки всех предметов за один раз, мне было интересно, как я могу загрузить элементы в партиях?

Так, например, если я использовал ListBox, с его параметрами ItemsSource, установленным в некоторый большой список, как я мог создать ListBoxItems в партиях, например, 10 элементов, отложив оставшиеся, чтобы выполнить их в следующем событии Dispatcher (Background или Background) AppIdle)?

Эта проблема может быть решена довольно легко с ViewModel, поскольку коллекция ItemsSource является наблюдаемой, которая растет с каждой новой партией, но я хочу добавить это на уровне представления.

Я также не хочу, чтобы он реализовывался с использованием свойства видимости ItemContainers, поскольку это, скорее всего, уже используется.

ответ

0

Это все будет зависеть от того, откуда берутся данные. Но я могу сказать, что загрузка с точки зрения - это всего лишь плохая идея.

  1. Настройте свой ItemsSource на ObservableCollection в вашей модели ViewModel.
  2. Обновите ObservableCollection из фонового потока, чтобы он не повлиял на ваш пользовательский интерфейс.
  3. При обновлении убедитесь, что вы не восстановите экземпляр, а скорее очистите и заселите свою коллекцию.

Я считаю, что WPF теперь позволяет передавать обновления в ObserverableCollection. Если нет, вы всегда можете использовать библиотеку, например Caliburn, для нее BindableCollection.

Вы также можете создать свой собственный, как this article.

Код:

/// <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 
} 
+0

Как я уже упоминал в моем вопросе, я знаю, что могу сделать это довольно легко из ViewModel. – pastillman

Смежные вопросы