Efficiensys
Efficiensys

Reputation: 15

WPF ContextMenu closing when MenuItem has StackPanel, how to keep it opened even on the first click ?

I created a ContextMenu with several MenuItems. When the user clicks on a Label the ContextMenu disappear but I want to keep it Opened. The aims is to avoid the reopen the menu when the user miss click a textbox or a checkbox.

The XAML code is :

  <ContextMenu 
                x:Key="contextMenuListeNew"   
                Name="contextMenuUser"
                StaysOpen="True"    
                >
            <MenuItem 
                    Header="Justifier"                     
                    Name="contextMenuJustifier"         
                    StaysOpenOnClick="True"
                    >
            </MenuItem>
            <MenuItem 
                Header="Corriger" 
                Name="MenuItemModifier"
                StaysOpenOnClick="True"
                IsSubmenuOpen="True"
                MouseLeftButtonDown="MenuItem_MouseLeftButtonDown"
                >
                <StackPanel 
                                Orientation="Horizontal"
                                Margin="2,0,0,0"
                                MouseLeftButtonDown="MenuItem_MouseLeftButtonDown"

                                >
                    <Label 
                        Name="LabelDispo" 
                        Content="Dispo"
                        MouseLeftButtonDown="MenuItem_MouseLeftButtonDown"

                        />
                    <TextBox
                                    Name="TextBoxDispoBrute"
                                    Text=""
                                    VerticalContentAlignment="Center"
                                    MouseLeftButtonDown="MenuItem_MouseLeftButtonDown"
                                    Width="60"
                                />
                    <Label 
                            Name="LabelPourcentage" 
                            MouseLeftButtonDown="MenuItem_MouseLeftButtonDown"
                            Content="%" />
                    <CheckBox
                                    Name="CheckBoxAllCells"
                                    Margin="0,5,0,0"
                                    MouseLeftButtonDown="MenuItem_MouseLeftButtonDown"
                                    Content="dont les 100%"
                                 />
                </StackPanel>
                <StackPanel 
                        Orientation="Horizontal"
                        MouseLeftButtonDown="MenuItem_MouseLeftButtonDown"
                        Margin="0,5,0,0">
                    <Label 
                        Content="Commentaire"
                        MouseLeftButtonDown="MenuItem_MouseLeftButtonDown"/>
                    <TextBox
                            Name="TextBoxCommentaireDispo"
                            Height="25"
                            MouseLeftButtonDown="MenuItem_MouseLeftButtonDown"  
                            Width="135"
                            VerticalContentAlignment="Center"
                            Text=""
                            />
                </StackPanel>
                <Separator />
                <Button 
                        Content="OK"
                        MouseLeftButtonDown="MenuItem_MouseLeftButtonDown"
                        Name="ButtonValiderDispo"                                        
                        Width="80"
                        Height="20"
                        />
            </MenuItem>
            <MenuItem 
                Header="RéInitialiser" 
                Name="MenuItemReset" 
                StaysOpenOnClick="True"
                >
            </MenuItem>
        </ContextMenu>

It looks like something like that ContextMenu

So when the user click on "Dispo" or "Commentaire" the contextmenu will close.

With the property StaysOpenOnClick="True" the MenuItem stays open only if its contains only a Name to click.

So "Justifier" and Réinitialiser" stays open thanks to this property. But it does not works when a add a stack panel with several elements like in the item "Corriger".

I found a first kind of workaround with the method :

Click="MenuItem_Click" that is placed on the MenuItem with this implementation :

private void MenuItem_Click(object sender, RoutedEventArgs e)
    {
        (e.OriginalSource as MenuItem).StaysOpenOnClick = true;
        (e.OriginalSource as MenuItem).IsSubmenuOpen = true;
        (e.Source as MenuItem).StaysOpenOnClick = true;
        (e.Source as MenuItem).IsSubmenuOpen = true;
    }

With this code the ContextMenu stays open only after the second click. On the first One the ContextMenu steal close but after it stays opened.

Do you know how to do it even at the first Click ?

Best Regards,

Upvotes: 1

Views: 1093

Answers (2)

Sinatr
Sinatr

Reputation: 21999

See this answer, to prevent menu item from closing menu you have to use a trick where your content is put inside MenuItem.Header (can be nested inside other MenuItem):

<Grid Background="White">
    <Grid.ContextMenu>
        <ContextMenu StaysOpen="True"> <!-- important -->
            <MenuItem Header="1" />

            <MenuItem Header="2"
                      StaysOpenOnClick="True"> <!-- important -->
                <MenuItem StaysOpenOnClick="True"> <!-- nested MenuItem -->
                    <MenuItem.Header>
                        <TextBox Width="60" /> <!-- content goes here -->
                    </MenuItem.Header>
                </MenuItem>
            </MenuItem>

            <MenuItem Header="3" />
        </ContextMenu>
    </Grid.ContextMenu>
</Grid>

Upvotes: 0

grek40
grek40

Reputation: 13438

Basically, you have a little misconception of what happens with the content of a MenuItem. Content elements that are not MenuItem or Separator themself, will be wrapped in MenuItem in the visual tree. So the following

<MenuItem Header="Corriger" StaysOpenOnClick="True">
    <StackPanel Orientation="Horizontal" Margin="2,0,0,0">
        <Label Content="Dispo" />
        <TextBox Text="" VerticalContentAlignment="Center" Width="60" />
        <Label Content="%" />
        <CheckBox Margin="0,5,0,0" Content="dont les 100%" />
    </StackPanel>
    <StackPanel Orientation="Horizontal" Margin="0,5,0,0">
        <Label Content="Commentaire"/>
        <TextBox Height="25" Width="135" VerticalContentAlignment="Center" Text="" />
    </StackPanel>
    <Separator />
    <Button Content="OK" Width="80" Height="20" />
</MenuItem>

will (roughly and incompletely) translate into this:

<MenuItem Header="Corriger" StaysOpenOnClick="True">
    <MenuItem>
        <MenuItem.Header>
            <StackPanel Orientation="Horizontal" Margin="2,0,0,0">
                <Label Content="Dispo" />
                <TextBox Text="" VerticalContentAlignment="Center" Width="60" />
                <Label Content="%" />
                <CheckBox Margin="0,5,0,0" Content="dont les 100%" />
            </StackPanel>
        </MenuItem.Header>
    </MenuItem>
    <MenuItem>
        <MenuItem.Header>
            <StackPanel Orientation="Horizontal" Margin="0,5,0,0">
                <Label Content="Commentaire"/>
                <TextBox Height="25" Width="135" VerticalContentAlignment="Center" Text="" />
            </StackPanel>
        </MenuItem.Header>
    </MenuItem>
    <Separator />
    <MenuItem>
        <MenuItem.Header>
            <Button Content="OK" Width="80" Height="20" />
        </MenuItem.Header>
    </MenuItem>
</MenuItem>

You see the missing StaysOpenOnClick="True" on the inner auto-generated items, right?

Solution: I suspect you don't actually need so many menu items on this inner level, but you need to make the menu items explicit or use some style to ensure the StaysOpenOnClick. Here is a solution with an explicit item:

<MenuItem Header="Corriger" StaysOpenOnClick="True">
    <MenuItem StaysOpenOnClick="True">
        <MenuItem.Header>
            <StackPanel>
                <StackPanel Orientation="Horizontal" Margin="2,0,0,0">
                    <Label Content="Dispo" />
                    <TextBox Text="" VerticalContentAlignment="Center" Width="60" />
                    <Label Content="%" />
                    <CheckBox Margin="0,5,0,0" Content="dont les 100%" />
                </StackPanel>
                <StackPanel Orientation="Horizontal" Margin="0,5,0,0">
                    <Label Content="Commentaire"/>
                    <TextBox Height="25" Width="135" VerticalContentAlignment="Center" Text="" />
                </StackPanel>
                <Separator />
                <Button Content="OK" Width="80" Height="20" />
            </StackPanel>
        </MenuItem.Header>
    </MenuItem>
</MenuItem>

If you don't like the highlight of the whole area, use multiple explicit sub-menu items or more explicit design with style and/or templates.

Upvotes: 0

Related Questions