Pregunta

Quiero ser capaz de dibujar en la parte superior de un TextBlock, y han encontrado una manera de hacer esto, pero no puedo quitar el dibujo una vez que está allí. Aquí está el código.

   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;
      }
   }

Razón por la que desee hacer esto: tenemos una cuadrícula de datos con una gran cantidad de células, cada célula mostrar el texto. mostramos alguna información de validación de las células y lo hacemos mediante el uso de una plantilla con un bloque de texto y algunos caminos Hosten en una cuadrícula. la sobrecarga de esto agrega elementos extra al árbol visual y cuando tenemos que volver a dibujar (en la carga, el cambio de ventanas o de una especie) que lleva mucho más tiempo los más elementos en el árbol visual. cuando es sólo un bloque de texto se trata de 1.3 a 1.2 más rápido que tener el control de una rejilla. Así que nos gustaría llamar la validación de nuestras cosas en la parte superior derecha del cuadro de texto.

¿Fue útil?

Solución

Sus problemas son los siguientes:

  1. GetVisualChild () debe devolver base.GetVisualChild (índice), excepto cuando el índice == base.VisualChildrenCount.
  2. Usted se olvidó de llamar AddVisualChild () cuando DrawingExtra llega a ser verdad o cambia DrawingVisual
  3. Usted se olvidó de llamar RemoveVisualChild () cuando DrawingExtra se convierte en falsa o cambia DrawingVisual

Puede solucionar # 2 y # 3 mediante el establecimiento de un PropertyChangedCallback en DrawingExtra y añadiendo código al colocador de DrawingVisual.

Explicación: Es la llamada AddVisualChild () que realmente añade la visual al árbol. Lo que ocurre es que su visual está siendo encuentran y se muestran "accidentalmente" a causa de su error en GetVisualChild (), pero no está siendo adecuadamente vinculado en el árbol visual por lo que vas a encontrar muchos problemas.

Actualizar

He editado el código como se describió anteriormente, y funcionó perfectamente. Estos son los cambios:

...
      {
        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);
  }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top