2010-03-22 8 views
1

ItemsPanel으로 사용할 때 컨테이너를 재활용하는 사용자 지정 Canvas을 구현하고 싶습니다. 그래서 VirtualizingPanel에서 파생되었으며 ArrangeOverrideMeasureOverride을 재정의했습니다. 나는이 같은 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; 
     } 
    } 

, 내가 먼저 새 항목을 추가하고 나는 오래된 것들을 제거한다. 재활용을 사용하는 경우 재활용 컨테이너를 얻으면 GenerateNext를 호출하여 얻는 new-Flag도 false라는 사실을 알아야합니다.

는 여기에서 우리는 새로운 항목을 추가

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