2010-06-24 60 views
1

我希望能夠繪製到TextBlock的頂部,並找到了一種方法來完成此操作,但是一旦圖形出現,我就無法刪除它。這是代碼。WPF:在TextBlock頂部繪圖

public class DerivedTextBlock : TextBlock { 

     public Boolean DrawExtra { 
     get { return (Boolean)GetValue(DrawExtraProperty); } 
     set { SetValue(DrawExtraProperty, value); } 
     } 

     // Using a DependencyProperty as the backing store for DrawExtra. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty DrawExtraProperty = 
      DependencyProperty.Register("DrawExtra", typeof(Boolean), typeof(DerivedTextBlock), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsArrange)); 

     public DrawingVisual DrawingVisual { get; set; } 

     public DerivedTextBlock() { 
     DrawingVisual = this.CreateDrawingVisualRectangle(); 
     } 

     protected override int VisualChildrenCount { 
     get { 
      //if we want to draw our extra info, add one to 
      // our visualChildrenCount, usually with a textblock it is 0 
      if (DrawExtra) { 
       return base.VisualChildrenCount + 1; 
      } 
      else { 
       return base.VisualChildrenCount; 
      } 
     } 
     } 

     protected override Visual GetVisualChild(int index) { 
     return DrawingVisual; 
     } 

     // Create a DrawingVisual that contains a rectangle. 
     private DrawingVisual CreateDrawingVisualRectangle() { 
     DrawingVisual drawingVisual = new DrawingVisual(); 

     // Retrieve the DrawingContext in order to create new drawing content. 
     DrawingContext drawingContext = drawingVisual.RenderOpen(); 

     // Create a rectangle and draw it in the DrawingContext. 
     Rect rect = new Rect(new Point(10.0, 0), new Size(10.0/2.0, 10)); 
     drawingContext.DrawRectangle(Brushes.LightBlue, (Pen)null, rect); 

     // Persist the drawing content. 
     drawingContext.Close(); 

     return drawingVisual; 
     } 
    } 

我想這樣做的原因:我們有一個包含很多單元格的數據網格,每個單元格都顯示文本。我們在單元上顯示一些驗證信息,我們通過使用帶有textblock和網格中的某些路徑hosten的模板來實現此目的。這增加了額外的元素到可視化樹中,當我們必須重新繪製(加載,切換窗口或排序)時,視覺樹中的元素越多,花費的時間就越長。當它只是一個文本塊時,比用網格控制要快大約1/3 - 1/2。所以我們想在文本框的頂部繪製我們的驗證內容。

回答

2

你的問題是:

  1. GetVisualChild()應除非指數== base.VisualChildrenCount返回base.GetVisualChild(指數)。
  2. 你忘了打電話給AddVisualChild()時DrawingExtra爲真或DrawingVisual改變
  3. 你忘了打電話給RemoveVisualChild()時DrawingExtra爲假或DrawingVisual改變

您可以通過設置固定#2,#3 DrawingExtra上的PropertyChangedCallback並將代碼添加到DrawingVisual的setter中。

說明:它實際上是將視覺添加到樹中的AddVisualChild()調用。發生的事情是,由於GetVisualChild()中的錯誤,您的視覺被「意外」發現並顯示,但它沒有正確鏈接到視覺樹中,因此您會遇到許多問題。

更新

我編輯的代碼,如上所述,它完美地工作。這裏是變化:

... 
     { 
     PropertyChangedCallback = (obj, e) => 
      { 
      var textBlock = (DerivedTextBlock)obj; 
      if((bool)e.OldValue) textBlock.RemoveVisualChild(textBlock.DrawingVisual); 
      if((bool)e.NewValue) textBlock.AddVisualChild(textBlock.DrawingVisual); 
      } 
     }); 

    public DrawingVisual DrawingVisual 
    { 
    get { return _drawingVisual; } 
    set 
    { 
     if(DrawExtra) RemoveVisualChild(_drawingVisual); 
     _drawingVisual = value; 
     if(DrawExtra) AddVisualChild(_drawingVisual); 
    } 
    } 
    private DrawingVisual _drawingVisual; 

... 

    protected override int VisualChildrenCount 
    { 
    get { return base.VisualChildrenCount + (DrawExtra ? 1 : 0); } 
    } 

    protected override Visual GetVisualChild(int index) 
    { 
    return index==base.VisualChildrenCount ? DrawingVisual : base.GetVisualChild(index); 
    } 
+0

我試過AddVisualChild(),它似乎它被忽略的TextBlock,所以我上面的解決方案是一個破解。 – 2010-06-24 07:58:47

+1

我剛剛嘗試了您的代碼,並提供了我所建議的更改,並且工作完美。然後,我爲DrawExtra屬性製作了一個動畫,並獲得了一個閃爍的藍色小框。 – 2010-06-24 08:30:44

+0

完全神奇,非常感謝! – 2010-06-24 23:10:24