为窗口中的每个按钮创建一个MouseEnter事件

本文关键字:一个 事件 MouseEnter 按钮 窗口 创建 | 更新日期: 2023-09-27 18:17:06

几个月前我一直在开发一个应用程序,我的朋友和我想与其他朋友分享这个应用程序,我需要显示一些帮助,使应用程序更容易,因为它是专为我们俩设计的。

出现的想法是,每次从按钮弹出悬停事件时,在文本块上显示帮助。所以我们添加了一个textBlock。现在我们仍然面临的问题是如何在主窗口中为每个按钮创建悬停事件,这个窗口中有很多按钮,所以我们不能在XAML代码中为每个按钮添加事件。

我期望从这个答案是一种方式来添加悬停事件在主窗口编程的所有按钮?

编辑:经过一些谷歌搜索和帮助,我可以做以下事情:
foreach (UIElement btn in GeneralMenuGrid.Children)
        {
            if (btn is Button)
            {
                Button currentButton = (Button)btn;
                currentButton.Content = "test";
            }
        }

这只是一个测试,将允许在GeneralMenuGrid控件中的所有按钮有一个content: test,现在的问题是,我在这个网格中嵌套的控件,我怎么能达到他们?

编辑:经过多年的眼睛,我要循环遍历我的窗口中的所有按钮:

public static void EnumVisuals(Visual argVisual, Window currentWindow)
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(argVisual); i++)
        {
            Visual childVisual = (Visual) VisualTreeHelper.GetChild(argVisual, i);
            if (childVisual is Button)
            {
                var button = childVisual as Button;
                button.MouseEnter += AllButtonsOnMouseEnter;
            }

            EnumVisuals(childVisual, currentWindow);
        }
    }

现在在AllButtonsOnMouseEnter函数中,我无法访问按钮,我将其设置为公共…我不能从这个类访问它,我怎么能用事件参数发送窗口?

为窗口中的每个按钮创建一个MouseEnter事件

您写道,"这个窗口中有很多按钮,所以我们不能在XAML代码中为每个按钮添加一个事件。"但是你可以添加一个适用于所有按钮的样式:

<Style TargetType="{x:Type Button}">
  <EventSetter Event="MouseEnter" Handler="Button_MouseEnter"/>
</Style>

我不知道你打算如何获得与每个按钮相关的帮助文本,但是很容易将其存储在按钮的标签中:

<Button Tag="Instantly move from one place to another.">
Teleport
</Button>

然后编写一个事件处理程序,在TextBlock中显示帮助:

private void Button_MouseEnter(object sender, MouseEventArgs e)
{
    Button button = sender as Button;
    textblock_that_shows_help.Text = button.Tag;
}

我创建了一个这样做的扩展方法,改编自这里:通过键入

查找WPF窗口中的所有控件

把这个类放到项目的某个地方:

public static class VisualTreeSearch
{
    /// <summary>
    /// Finds all elements of the specified type in the <see cref="System.Windows.DependencyObject"/>'s visual tree using a breadth-first search.
    /// </summary>
    /// <typeparam name="T">The type of element to search for.</typeparam>
    /// <param name="root">The object to search in.</param>
    /// <returns>A list of elements that match the criteria.</returns>
    public static IEnumerable<T> Find<T>(this DependencyObject root) where T : DependencyObject
    {
        return root.Find<T>(false, true);
    }
    /// <summary>
    /// Finds all elements of the specified type in the <see cref="System.Windows.DependencyObject"/>'s visual tree.
    /// </summary>
    /// <typeparam name="T">The type of element to search for.</typeparam>
    /// <param name="root">The object to search in.</param>
    /// <param name="depthFirst">True to do a depth-first search; false to do a breadth-first search</param>
    /// <param name="includeRoot">True to include the root element in the search; false to exclude it</param>
    /// <returns>A list of elements that match the criteria.</returns>
    public static IEnumerable<T> Find<T>(this DependencyObject root, bool depthFirst, bool includeRoot) where T : DependencyObject
    {
        if (includeRoot)
        {
            var depRoot = root as T;
            if (depRoot != null)
                yield return depRoot;
        }
        var searchObjects = new LinkedList<DependencyObject>();
        searchObjects.AddFirst(root);
        while (searchObjects.First != null)
        {
            var parent = searchObjects.First.Value;
            var count = VisualTreeHelper.GetChildrenCount(parent);
            var insertAfterNode = depthFirst ? searchObjects.First : searchObjects.Last;
            for (int i = 0; i < count; i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(parent, i);
                var depChild = child as T;
                if (depChild != null)
                    yield return depChild;
                insertAfterNode = searchObjects.AddAfter(insertAfterNode, child);
            }
            searchObjects.RemoveFirst();
        }
    }
}

要使用扩展方法,在窗口类中编写以下代码(作为示例)。这段代码循环遍历this(在本例中应该是您的Window)的所有子代、孙辈等,并找到所有Button元素。

foreach (var button in this.Find<Button>())
{
    button.MouseEnter += button_MouseEnter;
}
...
private void button_MouseEnter(object sender, MouseEventArgs e)
{
    // Do stuff
}

经过大量的谷歌搜索和聊天帮助…我终于做到了,也许其他人会感兴趣,这就是我是如何进行的:

我创建了一个静态递归函数,它将获取窗口中的所有按钮:

public static void EnumVisuals(Visual argVisual, Button toModifyButton)
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(argVisual); i++)
        {
            Visual childVisual = (Visual) VisualTreeHelper.GetChild(argVisual, i);
            if (childVisual is Button)
            {
                var button = childVisual as Button;
                button.MouseEnter += (sender, eventArgs) =>
                {
                    toModifyButton.Content = "Get the Help text from database if you want";
                };
            }

            EnumVisuals(childVisual, toModifyButton);
        }
    }

为什么要发送Button:

我需要在一个按钮中写帮助,我发现访问它的内容属性的唯一方法是通过这个函数发送它,当然让它公开。

希望对你有帮助