Jon Kragh
Jon Kragh

Reputation: 4719

Is there a way to programatically close a menuitem in WPF

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

Upvotes: 9

Views: 6928

Answers (3)

Velibor
Velibor

Reputation: 1

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

Upvotes: 2

Steve
Steve

Reputation: 181

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

Upvotes: 5

Kent Boogaart
Kent Boogaart

Reputation: 178820

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

Upvotes: 13

Related Questions