2010-06-24 2 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; 
     } 
    } 

이유는 내가이 작업을 수행 할 수 : 우리는 세포의 많은 데이터 그리드를 가지고, 각 셀은 텍스트를 표시. 우리는 셀에 대한 유효성 검사 정보를 보여주고 우리는 텍스트 블록이있는 템플릿과 그리드에 hosten하는 일부 경로를 사용하여이 작업을 수행합니다. 이 오버 헤드로 인해 시각적 트리에 추가 요소가 추가되고로드 할 때 또는 창을 전환하거나 정렬 할 때 다시 그리기해야하는 경우 시각적 트리에서 더 많은 요소가 더 오래 걸립니다. 그냥 텍스트 블록 일 때 그리드로 컨트롤하는 것보다 약 1/3 - 1/2 빠릅니다. 그래서 우리는 텍스트 상자 위에 유효성 검증 기능을 그리기를 원합니다.

답변

2

귀하의 문제는 다음과 같습니다

  1. GetVisualChild를 재정의은() 할 때 인덱스 == base.VisualChildrenCount 제외 base.GetVisualChild (인덱스)를 반환해야합니다.
  2. 당신은 DrawingExtra 사실 지거나 DrawingVisual과는
  3. 당신은 DrawingExtra이 거짓이되면 RemoveVisualChild()를 호출하는 것을 잊었다 변경 될 때 AddVisualChild()를 호출하는 것을 잊었다 또는 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에 대해 무시 된 것 같습니다. 위의 솔루션은 해킹입니다. –

+1

방금 ​​제안한 변경 사항으로 코드를 시도했지만 완벽하게 작동했습니다. 그런 다음 DrawExtra 속성에 애니메이션을 적용하고 파란색 상자가 깜박입니다. –

+0

완전히 마술, 정말 고마워! –