AdornerDecorator that lets some adorners pass?

738 views Asked by At

Question: Is it possible to create an AdornerDecorator that takes only the Adorners I want to its AdornerLayer?

public class SimpleCircleBehavior : Behavior<TextBox>
{
    private SimpleCircleAdorner sca;
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.Loaded += new RoutedEventHandler(AssociatedObject_Loaded);
    }

    void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
    {
        sca = new SimpleCircleAdorner(AssociatedObject);
        AdornerLayer.GetAdornerLayer(AssociatedObject).Add(sca);
    }
}

public class SimpleCircleAdorner : Adorner
{
    // Be sure to call the base class constructor.
    public SimpleCircleAdorner(UIElement adornedElement)
        : base(adornedElement)
    {
    }

    // A common way to implement an adorner's rendering behavior is to override the OnRender
    // method, which is called by the layout system as part of a rendering pass.
    protected override void OnRender(DrawingContext drawingContext)
    {
        Rect adornedElementRect = new Rect(this.AdornedElement.DesiredSize);

        // Some arbitrary drawing implements.
        SolidColorBrush renderBrush = new SolidColorBrush(Colors.Green);
        renderBrush.Opacity = 0.2;
        Pen renderPen = new Pen(new SolidColorBrush(Colors.Navy), 1.5);
        double renderRadius = 5.0;

        // Draw a circle at each corner.
        drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.TopLeft, renderRadius, renderRadius);
        drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.TopRight, renderRadius, renderRadius);
        drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.BottomLeft, renderRadius, renderRadius);
        drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.BottomRight, renderRadius, renderRadius);
    }
}

How can I add AdornerDecorator inside a TextBox, and put that adorner inside that layer? Inside the behavior of course, designer shouldn't care about adding AdornerDecorator on all elements that have adorners...

Preferably only this adorner should go there, and not steal all other adorners.

You cannot predict when creating adorners which layer the adorner appears...

Unless you create AdornerDecorator. Thats it! You can't know in advance on which layer they appear, they are not designed to work that way. This makes the whole thing just plain agony.

Imagine that you are creating adorner that works only on TextBox. To make it work and act along the TextBox you need AdornerDecorator to keep your adorners on top of TextBox.

  1. How do you create AdornerDecorator to wrap element you are about to adorn? Oh yeah, that is not possible (not that I know of) during creation of adorner.
  2. If you somehow manage to create AdornerDecorator you still have problems: it steals all the adorners in childs, and puts to this layer. Once again... WTF! How can I assume that all child element adorners, even the once I have not created, should go to this layer?

Other words, there are no way to control which layer your adorner appears if you don't specifically know all child elements and their adorners also. Thats whole lot of knowing when creating innocent sprinkles.

Workaround possibility:

  1. Create special AdornerDecorator that grabs only the adorners we know we want on it, others it would let go to next "global" AdornerDecorator.
  2. Somehow make the adorner wrap the inners of adorned element with this decorator, and add our adorners just inside this decorator.

I don't like this workaround, but bad design decisions sometimes need very ugly hacks... I think this time we need this.

0

There are 0 answers