Chengting
Chengting

Reputation: 355

How to Get contextmenu object in opening event

When contextmenu is opening, I want to fill a textbox with source control's information, for example its name and so on, for viewing and editing purpose.

But I however cannot access the opening contextmenu anyway. Maybe this is because my less understanding of control's xaml style.

The following is my xaml:

the context menu part: I want to fill the TextBox when contextmenu is opening.

<ContextMenu x:Key="VacUnitContextMenu" >
    <MenuItem Header="Property">
        <MenuItem>
            <MenuItem.Header> 
                <StackPanel Orientation="Horizontal">
                    <Label Content="Name" />
                    <TextBox Width="60" Name="VacName" Margin="2,0" />
                </StackPanel>
            </MenuItem.Header>
        </MenuItem>
        <MenuItem Header="Get" Command="{x:Static s:DesignerCanvas.VacUnitNameGet}"/>
    </MenuItem>
    <MenuItem Header="X">
            <MenuItem Header="TEST" Command="{x:Static s:DesignerCanvas.XTest}">
                <MenuItem.Icon>
                    <Image Source="Images/SendToBack.png" Width="16"/>
                </MenuItem.Icon>
            </MenuItem>
    </MenuItem>
</ContextMenu>

the context menu is used in this way:

<!-- VacUnit Style -->
<Style TargetType="{x:Type s:VacUnit}"  >
    <Setter Property="MinWidth" Value="10"/>
    <Setter Property="MinHeight" Value="10"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type s:VacUnit}">
                <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}"
                      ContextMenu="{StaticResource VacUnitContextMenu}"                              
                      >
                                            
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

I use conextmenuopening event, and try to fill the textbox there, How to: Handle the ContextMenuOpening Event

But I cannnot get the contextmenu, it is null:

FrameworkElement fe = e.Source as FrameworkElement;
ContextMenu cm = fe.ContextMenu;

Many thanks in advance.

Ting

Upvotes: 0

Views: 1179

Answers (2)

mm8
mm8

Reputation: 169160

Getting a reference to the ContextMenu should be easy provided that you handle the ContextMenuOpening event for the Grid in the ControlTemplate:

<ControlTemplate TargetType="{x:Type s:VacUnit}">
    <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}"
          ContextMenu="{StaticResource VacUnitContextMenu}"
          ContextMenuOpening="Grid_ContextMenuOpening">
    </Grid>
</ControlTemplate>

What's a bit trickier is to get a reference to the TextBox. You need to wait until it has been loaded:

private void Grid_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
    Grid grid = (Grid)sender;
    ContextMenu cm = grid.ContextMenu;
    if (cm != null)
        cm.Opened += Cm_Opened;
}

private void Cm_Opened(object sender, RoutedEventArgs e)
{
    ContextMenu cm = (ContextMenu)sender;
    cm.Opened -= Cm_Opened;

    MenuItem header = cm.Items[0] as MenuItem;
    MenuItem child = header.Items[0] as MenuItem;
    StackPanel sp = child.Header as StackPanel;
    (sp.Children[1] as TextBox).Background = Brushes.Yellow;
}

Upvotes: 2

user2250152
user2250152

Reputation: 20615

Probably e.Source is not a Grid where the context menu is defined.

You can search parent elements until you will find the element where the context menu is.

private void Xxx_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
    var fe = e.Source as FrameworkElement;
    var contextMenu = FindContextMenu(fe);
    if(contextMenu != null)
    {
        // your code
    }
}

// helper
private ContextMenu FindContextMenu(FrameworkElement fe)
{
    if(fe == null)
    {
        return null;
    }
    if(fe.ContextMenu != null)
    {
        return fe.ContextMenu;
    }
    else
    {
        var parent = VisualTreeHelper.GetParent(fe) as FrameworkElement;
        return FindContextMenu(parent);
    }
}

Upvotes: 1

Related Questions