2010-03-22 2 views
1

Я хочу реализовать обычай Canvas, который перерабатывает контейнеры при использовании в качестве ItemsPanel. Поэтому я получил от VirtualizingPanel и переопределял ArrangeOverride и MeasureOverride. Я делаю поколение MeasureOverride так:Переработка контейнера для контейнеров WPF

var children = base.InternalChildren; 

var itemsControl = ItemsControl.GetItemsOwner(this); 
var itemsCount = itemsControl.Items.Count; 

IItemContainerGenerator generator = itemsControl.ItemContainerGenerator; 

var startPos = generator.GeneratorPositionFromIndex(0); 

using (generator.StartAt(startPos, GeneratorDirection.Forward, true)) 
{ 
    for (int i = 0; i < itemsCount; i++) 
    { 
     bool isNewlyRealized; 

     var child = generator.GenerateNext(out isNewlyRealized) as UIElement; 

     if (isNewlyRealized) 
     { 
      base.AddInternalChild(child); 
      generator.PrepareItemContainer(child); 
     } 

     child.Measure(constraint); 
    } 
} 

То, что я не знаю, как сделать переработку. Я попробовал что-то вроде:

protected override void OnItemsChanged(object sender, ItemsChangedEventArgs e) 
{ 
    switch (e.Action) 
    { 
     case NotifyCollectionChangedAction.Remove: 
     case NotifyCollectionChangedAction.Replace: 
     case NotifyCollectionChangedAction.Move: 
      IRecyclingItemContainerGenerator generator = ItemsControl.GetItemsOwner(this).ItemContainerGenerator; 
      generator.Recycle(e.Position, e.ItemUICount); 
      RemoveInternalChildRange(e.Position.Index, e.ItemUICount); 
      break; 
    } 
} 

Но это не работает. есть идеи как это сделать?

ответ

3

Посмотрите здесь: http://blogs.claritycon.com/blogs/lee_roth/default.aspx

я сделать рециркуляцию следующим образом:

В OnItemsChanged, я только называю RemoveInternalChildRange:

protected override void OnItemsChanged(object sender, ItemsChangedEventArgs args) 
    { 
     switch (args.Action) 
     { 
     case NotifyCollectionChangedAction.Remove: 
     case NotifyCollectionChangedAction.Replace: 
      RemoveInternalChildRange(args.Position.Index, args.ItemUICount); 
      break; 
     case NotifyCollectionChangedAction.Move: 
      RemoveInternalChildRange(args.OldPosition.Index, args.ItemUICount); 
      break; 
     } 
    } 

В Measure переопределение, я сначала добавить новые элементы, а затем Я удаляю старые. Если вы используете утилизацию, вы должны знать, что новый флаг, который вы получаете, вызывая GenerateNext, также является ложным, если вы получаете переработанный контейнер.

Здесь мы добавляем новые товары:

GeneratorPosition start = ItemContainerGenerator.GeneratorPositionFromIndex(iFirstItemIndex); 
     int iChildIndex = (start.Offset == 0) ? start.Index : start.Index + 1; 
     using (ItemContainerGenerator.StartAt(start, GeneratorDirection.Forward, true)) 
     { 
     for (int i = iFirstItemIndex; i <= iLastItemIndex; i++, iChildIndex++) 
     { 
      bool bNew; 
      UIElement element = (UIElement)ItemContainerGenerator.GenerateNext(out bNew); 
      //If we get a new instance 
      if (bNew) 
      { 
      if (iChildIndex >= Children.Count) AddInternalChild(element); 
      else InsertInternalChild(iChildIndex, element); 
      ItemContainerGenerator.PrepareItemContainer(element); 
      } 
      //If we get a recycled element 
      else if (!InternalChildren.Contains(element)) 
      { 
      InsertInternalChild(iChildIndex, element); 
      ItemContainerGenerator.PrepareItemContainer(element); 
      } 
      element.Measure(...); 
     } 
     } 

После добавления элементов мы убираем старые товары:

for (int i = Children.Count - 1; i >= 0; i--) 
     { 
     GeneratorPosition childGeneratorPosition = new GeneratorPosition(i, 0); 
     int iIndex = ItemContainerGenerator.IndexFromGeneratorPosition(childGeneratorPosition); 
     if (iIndex < iFirstItemIndex || iIndex > iLastItemIndex) 
     { 
      //remove() calls ItemContainerGenerator.remove() OR recycle(). Both works. 
      remove(childGeneratorPosition, 1); 
      RemoveInternalChildRange(i, 1); 
     } 
     } 

Я надеюсь, что я мог бы помочь вам.

+0

На самом деле, если вы перерабатываете, перед созданием новых контейнеров следует называть код «очистка» (ваш последний блок кода). Это потому, что вы хотите переработать доступные контейнеры * до того, как они нужны, а не после. Сохраняет несколько ненужных творений. – MarqueIV

+2

Ссылка больше не доступна. – Djof

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