Question

I have a menu in wpf that has an input box and a button on it. Once the user clicks the button I need to close the menu.

Is there a way to do this?

    <Menu x:Name="MainMenu">
        <MenuItem Header="Main">
            <MenuItem Header="SubMenu" x:Name="SubMenu">
                <StackPanel Orientation="Horizontal">
                    <TextBox Width="50" x:Name="TextBox" />
                    <Button Content="Click Me and Close" x:Name="Button" IsDefault="True"/>
                </StackPanel>
            </MenuItem>
        </MenuItem>

Thanks, Jon

Was it helpful?

Solution

Get hold of the MenuItem and do:

_menuItem.IsSubmenuOpen = false;

Easy way to get hold of it:

<Button x:Name="_button" Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type MenuItem}, AncestorLevel=2}"/>

Code-behind:

_button.Click += delegate
{
    (_button.Tag as MenuItem).IsSubmenuOpen = false;
};

OTHER TIPS

I find that using IsSubmenuOpen doesn't properly eliminate focus from the Menu containing the MenuItem (especially if the Menu is in a ToolBar - the top-level MenuItem remains Selected even though the menu is "Closed"). I find sending a MouseUp event to the MenuItem works better (in the button's, or nested control's, Click event handler):

        private void button_Click(object sender, RoutedEventArgs e) {
           Button b = sender as Button;

           if (b == null || !(b.Parent is MenuItem))
              return;

           MenuItem mi = b.Parent as MenuItem;

           mi.RaiseEvent(
              new MouseButtonEventArgs(
                 Mouse.PrimaryDevice, 0, MouseButton.Left
              ) 
              {RoutedEvent=Mouse.MouseUpEvent}
           );
        }

Steve thanks for your solution. That is actually right answer, and finally something that really works beside of tons of bad answers over the internet. I have a shorter (and more safe) solution based on your anwser. Because direct parent (e.Parent) of the button is not always MenuItem (from original answer that is StackPanel), your solution will not work. So just set the Name property of the MenuItem (Name="MyMenuItem") and hook this handler on the Button:

    private void Button_Click(object sender, RoutedEventArgs e) {
        MyMenuItem.RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left) {
            RoutedEvent = Mouse.MouseUpEvent
        });
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top