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

问题描述

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

但是无论如何我都无法访问打开的上下文菜单。 可能是我对控件的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 中处理 ContextMenuOpeningGrid 事件,获取对 ControlTemplate 的引用应该很容易:

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...