2013-01-11 33 views
12

Tôi đang cố tạo một điều khiển Graph bằng cách sử dụng một ListBox WPF. Tôi tạo ra Canvas của riêng mình có nguồn gốc từ một VirtualizingPanel và tôi xử lý việc thực hiện và ảo hóa của bản thân mình.WPF Listbox Virtualization tạo ra DisconnectedItems

Bảng điều khiển mặt hàng của hộp danh sách sau đó được đặt làm canvas ảo được tùy chỉnh của tôi.

Vấn đề tôi đang gặp phải xảy ra trong các tình huống sau:

  • ListBox Mục A được tạo ra đầu tiên.
  • Mục Hộp danh sách B được tạo ở bên phải của Mặt hàng A trên canvas.
  • Mục Hộp danh sách A được ảo hóa trước tiên (bằng cách xoay nó ra khỏi chế độ xem).
  • Mục Hộp danh mục B được ảo hóa thứ hai (một lần nữa bằng cách kéo nó ra khỏi chế độ xem).
  • Mang ListBox mục A và B theo quan điểm (ví dụ: hiện thực hóa chúng)
  • Sử dụng Snoop, tôi phát hiện rằng ListBox có tại 3 hạng mục, một trong số họ trở thành một "DisconnectedItem" nằm ngay bên dưới ListBox mục B.

Điều gì tạo ra "DisconnectedItem" này? Nếu tôi đã ảo hóa B trước, tiếp theo là A, mục này sẽ không được tạo. Lý thuyết của tôi là các mục ảo hóa trước các mục khác trong ListBox khiến trẻ em bị ngắt kết nối.

Vấn đề thậm chí còn rõ ràng hơn khi sử dụng biểu đồ có hàng trăm nút, khi tôi kết thúc với hàng trăm mục bị ngắt khi tôi xoay quanh.

Đây là một phần của mã cho vải:

/// <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

Bạn có đang tái chế bình chứa không? – Paparazzi

+0

@Blam: Tôi không nghĩ tôi là gì, bạn có ý gì khi tái chế hộp chứa? –

+0

Chỉ cần tìm kiếm msdn cho thùng chứa rác http://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizationmode.aspx Chỉ cần tiếp cận mà còn chỉ là một nhận xét – Paparazzi

Trả lời

7

Nó được sử dụng bất cứ khi nào một container được lấy ra từ cây thị giác, hoặc vì mục tương ứng đã bị xóa hoặc bộ sưu tập là làm mới, hoặc container đã được cuộn ra khỏi màn hình và được ảo hóa lại.

Đây là một lỗi được biết đến trong WPF 4

Xem this link for known bug, nó cũng có một cách giải quyết bạn có thể áp dụng.

EDIT:.

"Bạn có thể làm cho giải pháp của bạn mạnh mẽ hơn một chút bằng cách tiết kiệm một tham chiếu đến các đối tượng trọng điểm {DisconnectedItem} lần đầu tiên bạn nhìn thấy nó, sau đó so sánh với giá trị lưu sau đó

Chúng ta nên thực hiện một cách công khai để kiểm tra {DisconnectedItem}, nhưng nó trượt qua các vết nứt Chúng ta sẽ khắc phục điều đó trong một bản phát hành trong tương lai, nhưng bây giờ bạn có thể dựa vào thực tế là có một đối tượng {DisconnectedItem} duy nhất. "

Các vấn đề liên quan