2013-04-26 4 views
2

Je ne sais pas comment obtenir le parent d'un menuItem? Je cherchai arround mais ne peut pas obtenir une bonne réponse ...WPF get parent de menuItem

Mon XAML est:

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

Dans le code, lorsque je clique sur le submenuItem comme « MenuItemVideoDevices », une fonction de processus d'événement est déclenché , mais je ne sais pas comment obtenir le menu "Video" dans cette fonction.

Quelqu'un sait?

Répondre

0

MenuItem a une propriété Parent.

var parent = mi.Parent; 
+1

Bonjour, merci! mais j'ai trouvé le mi.Parent est nul! Est-ce que "Parent" signifie le parent menuItem? – user991800

1

Si vous avez trouvé que la propriété est MenuItem.Parentnull, votre code n'est pas aussi simple que ce que vous avez publié. Je mets ensemble la fenêtre XAML simple suivante, et il a bien fonctionné:

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

C'est, le gestionnaire d'événements Click peut récupérer avec succès le parent correct, attendu MenuItem en utilisant la propriété 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()); 
    } 
} 


Comme vous n'avez pas fourni a good, minimal, complete_ code example qui reproduit fidèlement votre problème, je ne peux pas dire avec certitude pourquoi la propriété Parent était null dans votre test. Cependant, je peux dire que dans mon propre scénario (celui qui m'a conduit à cette question), le problème est que mes enfants MenuItem s sont des modèles et ne se retrouvent donc pas avec une valeur non nulle dans la propriété Parent . Notez ce commentaire dans the documentation for the FrameworkElement.Parent property:

Pour les modèles, le parent du modèle sera éventuellement nul. Pour passer ce point et étendre dans l'arbre logique où le modèle est réellement appliqué, utilisez TemplatedParent.

J'ai trouvé que suivre ce conseil n'était pas simple. Ma propriété Parent était null depuis le début. Mais il en était de même pour la propriété TemplatedParent de l'objet TemplatedParentet parent logique (tel que récupéré par LogicalTreeHelper.GetParent()). Ce que je devais faire était de suivre l'arbre visuel jusqu'à trouver le premier nœud parent que avait avait un parent logique. À ce stade, j'ai pu utiliser la propriété TemplatedParent de ce nœud pour récupérer le parent MenuItem réel. J'ai écrit une méthode simple d'aide pour généraliser ceci. Jusqu'à présent, le seul scénario pour lequel je l'utilise est ce scénario , et je ne sais vraiment pas si c'est ce qui serait nécessaire dans d'autres cas. Mais cela fonctionne pour moi et semble être un bon point de départ au cas où je rencontrerais un problème similaire avec un autre objet enfant (ou quelqu'un d'autre).

Écrit comme une méthode d'extension, il ressemble à ceci:

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

Cela me permet de récupérer l'objet parent MenuItem pour tout objet MenuItem basé sur un modèle, sans avoir à introduire d'autres objets (évidemment, je aurais pu résoudre le problème en initialisant un champ statique quelque part et en récupérant sa valeur, mais c'est très hacky et hellip, je voulais quelque chose de plus généraliste et fiable).