6

我正在尝试在 WPF 中创建一个很好的“拖放区”,当某些东西被拖入主应用程序时,它会显示在装饰层中。问题是我没有从我的装饰器那里得到任何事件,即使根据文档它应该接收所有输入事件,因为它处于更高的 z 顺序。

为了调试我的问题,我创建了一个非常简单的示例,其中我有一个用户控件,其中只有一个按钮。此用户控件显示在装饰层中,但我无法单击该按钮。为什么?我做错了什么?

我的装饰类是这样构造的:

    public ShellOverlayAdorner(UIElement element, AdornerLayer adornerLayer)
        :base(element)
    {
        _adornerLayer = adornerLayer;

        _overlayView = new AdornedElement();
        _overlayView.AllowDrop = true;
        _adornerLayer.Add(this);
     }

并在主窗口中由

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        adornerLayer = AdornerLayer.GetAdornerLayer(MyTopGridWithButtonInIt);
        ShellOverlayAdorner shell = new ShellOverlayAdorner(MyTopGridWithButtonInIt, adornerLayer);

    }

我没有从我的控制中得到任何事件,即没有鼠标点击、鼠标悬停、按钮点击。我什至无法单击装饰层中的按钮。我做错了什么?

4

2 回答 2

12

我不知道您是否已经尝试过:如果您希望添加的元素对事件做出反应,我认为该元素必须绑定到装饰器的可视化树。做到这一点的方法是使用VisualCollection,初始化到装饰器本身,或者至少,它似乎是这样工作的:

    VisualCollection visualChildren;
    FrameworkElement @object;

    public CustomAdorner(UIElement adornedElement) :
        base(adornedElement)
    {
        visualChildren = new VisualCollection(this);
        @object = new Button {Content = "prova"};
        visualChildren.Add(@object);
    }
    protected override Visual GetVisualChild(int index)
    {
        return visualChildren[index];
    }

这样事件被正确路由。

于 2010-12-29T08:26:50.183 回答
1

我只是有同样的问题。按照 MSDN 的建议为我排序:

装饰器像任何其他 FrameworkElement 一样接收输入事件。因为装饰器的 z 顺序总是高于它所装饰的元素,所以装饰器接收可能用于底层装饰元素的输入事件(例如 Drop 或 MouseMove)。装饰器可以侦听某些输入事件,并通过重新引发事件将这些事件传递给底层装饰元素。

要启用装饰器下元素的直通命中测试,请将装饰器上的命中测试 IsHitTestVisible 属性设置为 false。

即在装饰器本身中,确保 IsHitTestVisible = false

于 2011-04-06T09:41:58.950 回答