首页 > 解决方案 > 如果 Adorner 直接显示在 WPF 控件之上,如何处理 WPF 中的 MouseEnter 和 MouseLeave 事件?

问题描述

我在 WPF 应用程序中有一个 ListView,我想通过自定义 Adorner 向每个 ListViewItem 添加一个带有一些按钮的网格。当前正在为 ListViewItem 触发 MouseEnter 事件时添加装饰器,例如,当我将鼠标移入 ListViewItem 时,并在 ListViewItem 上发生 MouseLeave 事件时移除。但是,这会导致 MouseEnter/MouseLeave 事件循环,因为添加 Adorner 时会导致 Adorner 成为鼠标的焦点,而不是 ListViewItem。换句话说,一旦添加了 Adorner,它就会因为 ListViewItem 触发的 MouseLeave 事件而立即被删除。

我已经看到了一些关于将“IsHitTestVisible = false”属性添加到 Adorner 的建议,但我需要能够捕获 Adorner 中按钮上的点击事件。

缩写装饰类


private readonly VisualCollection visualChildren;
private Grid adornerGrid;

public ListViewItemOptionsAdorner(UIElement adornedElement): base(adornedElement)
{
    visualChildren = new VisualCollection(this);
    adornerGrid = new Grid();
    Button editButton = new Button();
    Button deleteButton = new Button();

    adornerGrid.Children.Add(editButton);
    adornerGrid.Children.Add(deleteButton);

    visualChildren.Add(adornerGrid);

    MouseEnter += ListViewItemOptionsAdorner_MouseEnter;
    MouseLeave += ListViewItemOptionsAdorner_MouseLeave;

}

private void ListViewItemOptionsAdorner_MouseEnter { }

private void ListViewItemOptionsAdorner_MouseLeave { }

ListView 的主窗口函数

private void List_MouseEnter(object sender, MouseEventArgs e)
{
    ListViewItem listItem = sender as ListViewItem;
    AdornerLayer myAdornerLayer = AdornerLayer.GetAdornerLayer(listItem);
    myAdornerLayer.Add(new ListViewItemOptionsAdorner(listItem));

    e.Handled = true;
}

private void List_MouseLeave(object sender, MouseEventArgs e)
{
    ListViewItem listItem = sender as ListViewItem;

    if (!listItem.IsMouseOver)
    {
        AdornerLayer myAdornerLayer = AdornerLayer.GetAdornerLayer(listItem);
        Adorner[] adorners = myAdornerLayer.GetAdorners(listItem);
        for (int i = 0; adorners.Length; i++)
            myAdornerLayer.Remove(adorners[i]);
        e.Hanlded = true;
    }
}

所发生的只是一个连续的循环,其中装饰器会闪烁,但我希望它只在鼠标悬停在 ListViewItem 上时出现,而在不在 ListViewItem 上时隐藏。

标签: c#wpfmouseeventmouseenteradorner

解决方案


推荐阅读