2013-01-11 28 views
12

Bir WPF ListBox kullanarak Grafik denetimi oluşturmaya çalışıyorum. Bir VirtualizingPanel'den elde ettiğim kendi Canvas'ımı yarattım ve kendimdeki öğelerin gerçekleştirilmesini ve sanallaştırılmasını ele alıyorum.WPF Liste Kutusu Sanallaştırma DisconnectedItems'i oluşturur

Liste kutusu 'öğe paneli daha sonra özel sanallaştırılmış tuvalim olacak şekilde ayarlandı.

Ben karşılaşmamdır sorun aşağıdaki senaryoda oluşur:

  • ListBox Öğe ilk oluşturulur.
  • ListBox Öğesi B, tuvalde A Öğesinin sağında oluşturulur.
  • ListBox Öğesi A önce sanallaştırılır (görüntüyü kaydırmak suretiyle).
  • ListBox Öğesi B ikinci olarak sanallaştırılmıştır (tekrar görüntüyü kaydırmak suretiyle).
  • görünümünde liste kutusu Ürün A ve B getir: Snoop kullanma
  • , ben ListBox şimdi 3 öğe, liste kutusu Öğe B. hemen altında bulunan "DisconnectedItem" içlerinden birine sahip olduğunu tespit (yani onları gerçekleştirmek)

Bu "DisconnectedItem" ın oluşturulmasına neden olan nedir? Eğer önce B'yi sanallaştırırsam, onu A ile takip ettiysem, bu öğe yaratılmayacaktı. Benim teorim, bir ListBox'taki diğer öğelerin önündeki öğelerin sanallaştırılmasının, çocukların bağlantısının kesilmesine neden olmasıdır.

Sorun, yüzlerce düğüm içeren bir grafik kullanarak daha da belirgin hale geliyor; çünkü etrafta donduğumda yüzlerce bağlantısız öğe ile karşılaşıyorum. İşte

Tuval için kod kısmıdır:

/// <summary> 
/// Arranges and virtualizes child element positionned explicitly. 
/// </summary> 
public class VirtualizingCanvas : VirtualizingPanel 
{ 
    (...) 

    protected override Size MeasureOverride(Size constraint) 
    { 
     ItemsControl itemsOwner = ItemsControl.GetItemsOwner(this); 

     // For some reason you have to "touch" the children collection in 
     // order for the ItemContainerGenerator to initialize properly. 
     var necessaryChidrenTouch = Children; 

     IItemContainerGenerator generator = ItemContainerGenerator; 

     IDisposable generationAction = null; 

     int index = 0; 
     Rect visibilityRect = new Rect(
      -HorizontalOffset/ZoomFactor, 
      -VerticalOffset/ZoomFactor, 
      ActualWidth/ZoomFactor, 
      ActualHeight/ZoomFactor); 

     // Loop thru the list of items and generate their container 
     // if they are included in the current visible view. 
     foreach (object item in itemsOwner.Items) 
     { 
      var virtualizedItem = item as IVirtualizingCanvasItem; 

      if (virtualizedItem == null || 
       visibilityRect.IntersectsWith(GetBounds(virtualizedItem))) 
      { 
       if (generationAction == null) 
       { 
        GeneratorPosition startPosition = 
           generator.GeneratorPositionFromIndex(index); 
        generationAction = generator.StartAt(startPosition, 
              GeneratorDirection.Forward, true); 
       } 

       GenerateItem(index); 
      } 
      else 
      { 
       GeneratorPosition itemPosition = 
           generator.GeneratorPositionFromIndex(index); 

       if (itemPosition.Index != -1 && itemPosition.Offset == 0) 
       { 
        RemoveInternalChildRange(index, 1); 
        generator.Remove(itemPosition, 1); 
       } 

       // The generator needs to be "reseted" when we skip some items 
       // in the sequence... 
       if (generationAction != null) 
       { 
        generationAction.Dispose(); 
        generationAction = null; 
       } 
      } 

      ++index; 
     } 

     if (generationAction != null) 
     { 
      generationAction.Dispose(); 
     } 

     return default(Size); 
    } 

    (...) 

    private void GenerateItem(int index) 
    { 
     bool newlyRealized; 
     var element = 
      ItemContainerGenerator.GenerateNext(out newlyRealized) as UIElement; 

     if (newlyRealized) 
     { 
      if (index >= InternalChildren.Count) 
      { 
       AddInternalChild(element); 
      } 
      else 
      { 
       InsertInternalChild(index, element); 
      } 

      ItemContainerGenerator.PrepareItemContainer(element); 

      element.RenderTransform = _scaleTransform; 
     } 

     element.Measure(new Size(double.PositiveInfinity, 
           double.PositiveInfinity)); 
    } 
+0

Geri dönüşüm konteyneri misiniz? – Paparazzi

+0

@Blam: Ben sanmıyorum, kabı geri dönüştürerek ne demek istiyorsun? –

+0

Sadece geri dönüşüm kabı için msdn araması http://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizationmode.aspx Sadece bir erişim değil, aynı zamanda sadece bir yorum – Paparazzi

cevap

7

Bir kap görsel ağaçtan çıkarıldığında ya karşılık gelen öğe silindi çünkü kullanmış veya toplama yenilendiği veya var konteyner ekrandan kaydırıldı ve yeniden sanallaştırıldı.

Bu WPF 4

olduğu bilinen bir hata da uygulamak mümkün olabilir geçici bir çözüm vardır, this link for known bug Bkz olduğunu.

DÜZENLEME:.

"Ondan sonra kaydedilen değerden karşı karşılaştırarak sonra, sentinel nesne {DisconnectedItem} Onu ilk defa gördüklerinde bir başvuru kaydederek çözümü biraz daha sağlam yapabilir

{DisconnectedItem} için test etmenin genel bir yolunu yapmalıydık, ancak çatlaklardan geçtikten sonra gelecekteki bir sürümde bunu düzelteceğiz, ancak şimdilik benzersiz bir {DisconnectedItem} nesnesi olduğu gerçeğine güvenebilirsiniz. "