1

I've been working on an application months ago, my friend and i wanted to share this application with other friends, and i need to display some help to make the application easier because it was designed only for both of us.

The idea that came out is to display help on a text Block every time a hover event is popped from a button. So we added a textBlock. Now the problem that we still facing is how to create the Hover Event for every button in our Main Window, there are a lots of buttons in this window, So we can't add an event to every button in the XAML code.

What i am expecting from this answer is a way to add Hover Event to all buttons in the main window Programmatically ?

EDIT: after some googling and help, i can do the following :

foreach (UIElement btn in GeneralMenuGrid.Children)
        {
            if (btn is Button)
            {
                Button currentButton = (Button)btn;
                currentButton.Content = "test";
            }

        }

This is just a test that will allow all the buttons in the GeneralMenuGrid control to have a content : test, now the problem again is that i have nested controls in this grid, how can i reach them?

EDIT : after years of goggling i got to loop through all the buttons in my window with this :

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

now in the AllButtonsOnMouseEnter function, i can't access a button, i made it public... i can't access it from this class, how can i send the window with the event arguments?

Redaa
  • 1,540
  • 2
  • 17
  • 28
  • 2
    It sounds like you want use the [ToolTip property](http://msdn.microsoft.com/en-us/library/vstudio/system.windows.frameworkelement.tooltip.aspx), perhaps in conjunction with the [ToolTip control](http://msdn.microsoft.com/en-us/library/vstudio/system.windows.controls.tooltip.aspx) –  Aug 07 '14 at 23:51
  • @elgonzo i don't want to use a popup window, the text will be displayed in a textblock in the same window – Redaa Aug 07 '14 at 23:55
  • @elgonzo is there a way to just loop throught button controls and foreach one create a hover event ? – Redaa Aug 08 '14 at 00:00

3 Answers3

3

You wrote, "there are a lots of buttons in this window, so we can't add an event to every button in the XAML code." But you can - just add a style that applies to all buttons:

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

I don't know how you intend to get the help text relevant to each Button, but it's easy to store it in the Button's Tag:

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

Then write an event handler that shows the help in your TextBlock:

private void Button_MouseEnter(object sender, MouseEventArgs e)
{
    Button button = sender as Button;
    textblock_that_shows_help.Text = button.Tag;
}
sjw
  • 228
  • 1
  • 4
  • 8
2

I've created an extension method that does this, adapted from here: Find all controls in WPF Window by type

Put this class somewhere in your project:

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

To use the extension method, write the following in your window class (as an example). This code loops through all children, grandchildren, etc. of this (which should be your Window in this case) and finds all Button elements.

foreach (var button in this.Find<Button>())
{
    button.MouseEnter += button_MouseEnter;
}

...

private void button_MouseEnter(object sender, MouseEventArgs e)
{
    // Do stuff
}
Community
  • 1
  • 1
AJ Richardson
  • 6,610
  • 1
  • 49
  • 59
-2

after a lot of googling and chat help... i finally did it, maybe other will be interested this is how i proceeded :

i created a static recursive function that will get all the buttons in the window:

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

why do you send a Button :

i need to write the help in a button, and the only way i found to access it's content property is to send it via this function and of course make it public.

Hope you'll find this helpfull.

Redaa
  • 1,540
  • 2
  • 17
  • 28