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
テストに含まれていた理由を確実に言うことはできません。ただし、私自身のシナリオ (この質問に私を導いたもの) では、問題は私の子がテンプレートであるため、プロパティMenuItem
に null 以外の値が含まれていないことです。プロパティのドキュメントで次の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
ます (明らかに、静的フィールドをどこかで初期化し、その値を取得するだけで問題を解決できたはずですが、それは非常にハックです...もっと一般的なものが欲しかった-目的と信頼性)。