装饰器和装饰元素上的事件

5
我有一个自定义的线形状,使用装饰器在该线的中间显示一个数组和一些文本。
问题是,装饰器的行为与装饰元素独立,并且不会将事件“传递”给它。在下面的代码中,我被迫手动重新链接装饰器元素到装饰元素(`ta.MouseLeftButtonDown += Adorner_MouseLeftButtonDown;`),但不幸的是,即使这样也不起作用...... 有人能指导一下调用`this.OnMouseLeftButtonDown`时出了什么问题吗?为什么我没有收到相应的事件?
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;
        }
    }    
}

1
你可以通过将 IsHitTestVisible 设置为 false 来禁用装饰器上的所有事件。或者你想让一些事件由装饰器处理,另一些事件由 SegmentLine 处理吗? - alpha-mouse
@alpha-mouse:不,我希望adorner处理任何事件,但是如果我只设置IsHitTestVisible=false(如您在代码中所见),我根本就收不到事件。 - serhio
2个回答

5

在将事件传递到修饰元素时,应调用this.RaiseEvent(e);而不是this.OnMouseLeftButtonDown(e);
另外,您可以使用一个事件处理程序来传递多个事件类型。

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

1

我知道这已经过时了,但我遇到了类似的问题(在装饰器中未接收到事件),我通过在我的OnRender()方法中绘制透明背景来解决了这个问题。

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

没有背景,就没有事件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接