如何在打开事件中获取上下文菜单对象

How to Get contextmenu object in opening event

打开上下文菜单时,我想用源代码管理的信息填充一个文本框,例如它的名称等,以便查看和编辑。

但是无论如何我都无法访问打开的上下文菜单。 可能是我对control的xaml风格理解不够

以下是我的xaml:

上下文菜单部分:我想在上下文菜单打开时填充文本框。

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

上下文菜单是这样使用的:

<!-- 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>

我使用 conextmenuopening 事件,并尝试在那里填充文本框, How to: Handle the ContextMenuOpening Event

但是我无法获取上下文菜单,它是空的:

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

非常感谢。

可能 e.Source 不是定义上下文菜单的 Grid

您可以搜索父元素,直到找到上下文菜单所在的元素。

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

获取对 ContextMenu 的引用应该很容易,前提是您在 ControlTemplate:

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

有点棘手的是获取对 TextBox 的引用。您需要等待它加载完成:

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