Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adorner and Events on Adorned element

I have a custom Line Shape that use an adorner to display an array and some text in the middle of that line.

alt text

The problem is that the adorned behaves independently of the adorned element, and does not "transfer" the event to it. In the following code I am forced to manually relink the adorner elements to adorned element (ta.MouseLeftButtonDown += Adorner_MouseLeftButtonDown;), but unfortunately even this does not work... Could somebody advice what is wrong when calling this.OnMouseLeftButtonDown, why I don't receive the respective event?

public class SegmentLine : Shape
{
    AdornerLayer aLayer;

    public static readonly DependencyProperty X1Property;
    public static readonly DependencyProperty X2Property;
    public static readonly DependencyProperty Y1Property;
    public static readonly DependencyProperty Y2Property;
    ...

    static SegmentLine() {
        X1Property = DependencyProperty.Register("X1", typeof(double), typeof(SegmentLine), new FrameworkPropertyMetadata(double.NaN,
            FrameworkPropertyMetadataOptions.AffectsRender));
        X2Pro...
    }

    public SegmentLine()
        : base()
    {
        this.Loaded += SegmentLine_Loaded;
    }

    void SegmentLine_Loaded(object sender, RoutedEventArgs e)
    {
        aLayer = AdornerLayer.GetAdornerLayer(this);
        if (aLayer != null)
        {
            TextAdorner ta = new TextAdorner(this);
            //ta.IsHitTestVisible = false;
            ta.MouseLeftButtonDown += Adorner_MouseLeftButtonDown;
            aLayer.Add(ta);
        }
    }

    void Adorner_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        // !! try to rise the MouseLeftButtonDown event
        this.OnMouseLeftButtonDown(e);
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        base.OnRender(drawingContext);
        if (aLayer != null)
            aLayer.Update();
    }

    class TextAdorner : Adorner
    {
        public TextAdorner(UIElement adornedElement)
            : base(adornedElement) { }

        protected override void OnRender(DrawingContext drawingContext)
        {
            // ADD LABEL ...
            FormattedText ft = new FormattedText(...);
            drawingContext.DrawText(ft, midPoint);

            // Add ARROW ...
            var myPathGeometry = new PathGeometry { Figures = myPathFigureCollection };            
            drawingContext.DrawGeometry(Brushes.Black, null, myPathGeometry);
        }
    }

    protected override System.Windows.Media.Geometry DefiningGeometry
    {
        get
        {
            var geometryGroup = new GeometryGroup();
            // Add line
            geometryGroup.Children.Add(new LineGeometry(new Point(X1, Y1), new Point(X2, Y2)));
            return geometryGroup;
        }
    }    
}
like image 806
serhio Avatar asked Nov 18 '10 11:11

serhio


2 Answers

You should call this.RaiseEvent(e); instead of this.OnMouseLeftButtonDown(e); to transfer the event to the adorned element.
And by the way, you can use only one event handler to transfer several event types

void SegmentLine_Loaded(object sender, RoutedEventArgs e)
{
    ..
    ta.MouseLeftButtonDown += Adorner_AnyEvent;
    ta.MouseRightButtonDown += Adorner_AnyEvent;
}

void Adorner_AnyEvent(object sender, RoutedEventArgs e)
{
    this.RaiseEvent(e);
}
like image 115
alpha-mouse Avatar answered Sep 19 '22 13:09

alpha-mouse


I know this is old but I had a similar problem (not receiving events in Adorner), which I fixed by drawing a transparent background in my OnRender()

drawingContext.DrawRectangle(Brushes.Transparent, null, viewRect);

No background = no events.

like image 28
GazTheDestroyer Avatar answered Sep 20 '22 13:09

GazTheDestroyer