Question

Je veux être en mesure de tirer sur le haut d'un TextBlock, et ont trouvé un moyen de le faire, mais je ne peux pas enlever le dessin une fois qu'il est là. Voici le code.

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

La raison je veux faire ceci: Nous avons un DataGrid avec beaucoup de cellules, chaque cellule l'affichage du texte. nous montrons quelques informations de validation sur les cellules et nous le faisons en utilisant un modèle avec un TextBlock et quelques chemins Hosten dans une grille. les frais généraux de cela ajoute des éléments supplémentaires à l'arbre visuel et quand nous devons redessiner (sur le chargement, les fenêtres de commutation ou sur une sorte) il faut beaucoup plus les éléments les plus dans l'arborescence visuelle. quand il est juste un bloc de texte, il est d'environ 1.3-1.2 plus rapide que d'avoir le contrôle d'une grille. Donc, nous aimerions tirer droit nos affaires de validation au-dessus de la zone de texte.

Était-ce utile?

La solution

Vos problèmes sont les suivants:

  1. GetVisualChild () devrait retourner base.GetVisualChild (index), sauf si l'index == base.VisualChildrenCount.
  2. Vous avez oublié d'appeler AddVisualChild () lorsque DrawingExtra devient vrai ou DrawingVisual change
  3. Vous avez oublié d'appeler RemoveVisualChild () lorsque DrawingExtra devient fausse ou DrawingVisual change

Vous pouvez fixer # 2 et # 3 en définissant un PropertyChangedCallback sur DrawingExtra et en ajoutant du code pour le poseur de DrawingVisual.

Explication: Il est l'appel AddVisualChild () qui ajoute en fait le visuel à l'arbre. Ce qui se passe est que votre visuelle est trouvé et affiché « accidentellement » à cause de votre erreur dans GetVisualChild (), mais il n'est pas correctement lié dans l'arbre visuel de sorte que vous allez rencontrer de nombreux problèmes.

Mise à jour

Je modifié votre code comme décrit ci-dessus, et cela a fonctionné parfaitement. Voici les changements:

...
      {
        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);
  }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top