3

我不知道如何获取 menuItem 的父级?我搜索了所有arround,但无法得到一个好的答案......

我的 XAML 是:

<DockPanel>
            <Menu DockPanel.Dock="Right" SnapsToDevicePixels="True" Margin="2,0,0,0">
                <MenuItem Header="Devices">
                    <local:MenuItemWithRadioButton x:Name="MenuItemVideoDevices" Header="Video">
                    </local:MenuItemWithRadioButton>
                    <local:MenuItemWithRadioButton x:Name="MenuItemAudioDevices" Header="Audio">
                    </local:MenuItemWithRadioButton>
                </MenuItem>
            </Menu>
</DockPanel>

private void MenuItemWithRadioButtons_Click(object sender, System.Windows.RoutedEventArgs e)
{
        MenuItem mi = sender as MenuItem;
        if (mi != null)
        {
            RadioButton rb = mi.Icon as RadioButton;
            if (rb != null)
            {
                rb.IsChecked = true;
            }
            //Here I want to get the parent menuItem
        }            
}

在代码中,当我单击“MenuItemVideoDevices”之类的子菜单项时,会触发一个事件处理函数,但我不知道如何在该函数中获取menuItem“视频”。

有谁知道?

4

2 回答 2

2

如果您发现该MenuItem.Parent属性是null,那么您的代码并不像您发布的那么简单。我将以下简单的 XAML 窗口放在一起,它运行良好:

<Window x:Class="TestSO16231375MenuItemParent.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
  <DockPanel>
    <Menu DockPanel.Dock="Right" SnapsToDevicePixels="True" Margin="2,0,0,0">
      <MenuItem Header="Devices">
        <MenuItem x:Name="MenuItemVideoDevices" Header="Video" Click="MenuItemVideoAudioDevices_Click"/>
        <MenuItem x:Name="MenuItemAudioDevices" Header="Audio" Click="MenuItemVideoAudioDevices_Click"/>
      </MenuItem>
    </Menu>
  </DockPanel>
</Window>

也就是说,事件处理程序可以使用以下属性Click成功检索正确的预期MenuItem父级:Parent

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void MenuItemVideoAudioDevices_Click(object sender, RoutedEventArgs e)
    {
        MenuItem menuItem = (MenuItem)sender;

        MessageBox.Show("Parent's header text: " + ((MenuItem)menuItem.Parent).Header.ToString());
    }
}


由于您没有提供一个好的、最小的、完整的代码示例来可靠地重现您的问题,因此我无法确定为什么该Parent属性null在您的测试中。但是,我可以说,在我自己的场景中(导致我提出这个问题的场景),问题是我的 childMenuItem是模板,因此不会在Parent属性中得到非空值。请注意该属性文档中的FrameworkElement.Parent此注释:

对于模板,模板的 Parent 最终将为 null。要超越这一点并扩展到实际应用模板的逻辑树,请使用 TemplatedParent。

我发现遵循这个建议并不简单。我的Parent财产null从一开始就是。但是MenuItem对象的TemplatedParent属性逻辑父对象(由 检索LogicalTreeHelper.GetParent())也是如此。

我最终要做的是沿着可视化树向上找到第一个具有逻辑父节点的父节点。那时,我能够使用该节点的TemplatedParent属性来检索实际的MenuItem父节点。

我写了一个简单的辅助方法来概括这一点。到目前为止,我使用它的唯一场景就是这个MenuItem场景,我真的不知道这是否是其他情况下需要的。但它对我有用,并且似乎是一个很好的起点,以防我遇到与其他子对象(或其他任何人)类似的问题。

写成扩展方法,它看起来像这样:

public static T GetTemplatedParent<T>(this FrameworkElement o)
    where T : DependencyObject
{
    DependencyObject child = o, parent = null;

    while (child != null && (parent = LogicalTreeHelper.GetParent(child)) == null)
    {
        child = VisualTreeHelper.GetParent(child);
    }

    FrameworkElement frameworkParent = parent as FrameworkElement;

    return frameworkParent != null ? frameworkParent.TemplatedParent as T : null;
}

这使我可以检索MenuItem任何模板化对象的父对象MenuItem,而不必引入任何其他对象(显然我可以通过在某处初始化一些静态字段并检索其值来解决问题,但这非常hacky......我想要更通用的东西-目的和可靠)。

于 2015-06-18T23:19:49.233 回答
-2

MenuItem有一个属性Parent

var parent = mi.Parent;
于 2013-04-26T08:02:16.470 回答