WPF:テキストブロックの上に描画します
-
29-09-2019 - |
質問
私はテキストブロックの上部に描画できるようになりたいと思っています。これがコードです。
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;
}
}
私がこれをやりたい理由:私たちは多くのセルを備えたデータグリッドを持っています。各セルはテキストを表示します。セルに関する検証情報を表示し、テキストブロックを備えたテンプレートとグリッド内のいくつかのパスホステンを使用してこれを行います。これのオーバーヘッドは、視覚ツリーに追加の要素を追加し、再描画する必要がある場合(ロード、ウィンドウの切り替え、またはソートで)、視覚ツリーのより多くの要素の方がずっと時間がかかります。単なるテキストブロックの場合、グリッドでコントロールするよりも約1/3-1/2が高速です。したがって、テキストボックスの上に検証のものを描画したいと思います。
解決
あなたの問題は次のとおりです。
- getVisualChild()は、index == base.VisualChildRencountの場合を除き、base.getVisualChild(index)を返す必要があります。
- DrawingExtraがTRUEになったり、視点の変更を描画したりしたときに、addVisualChild()に電話するのを忘れました
- drawingExtraが虚偽または描画視界の変更になったときにremovevisualchild()に電話するのを忘れました
DrawingExtraにPropertyChangedCallbackを設定し、DrawingVisualのセッターにコードを追加することにより、#2と#3を修正できます。
説明:実際にツリーにビジュアルを追加するのは、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);
}
所属していません StackOverflow