2010-11-30 30 views
1

J'ai des données ListBox liées à la collection de ma classe PersonCollection. Ensuite, j'ai défini un modèle de données pour les objets de type Person, composé d'un DockPanel qui contient un TextBlock pour le nom d'une personne et un Button pour supprimer la personne de la liste. Ça a l'air très bien tous ensemble.Problème avec l'arbre d'éléments WPF traversant

Le problème auquel je suis confronté est que je suis incapable d'atteindre l'élément sélectionné (et de le supprimer) dans la zone de liste lorsque je clique sur le bouton défini dans le modèle de données. Voici le gestionnaire du bouton:

private void RemovePersonButton_Click(object sender, RoutedEventArgs e) 
{ 
    Button clickedButton = (Button)e.Source; 
    DockPanel buttonPanel = (DockPanel)clickedButton.Parent; 
    Control control = (Control)button.Parent; 
} 

Le dernier objet créé control est null, à savoir que je ne peux pas progresser l'arborescence des éléments, je ne peux pas accéder à la liste et son SelectedItem. Il est important de noter ici qu'il est impossible d'obtenir l'élément sélectionné dans la liste en l'appelant, car j'ai plusieurs listes dans la fenêtre et toutes ces listes implémentent le même modèle de données, c'est-à-dire partagent le même gestionnaire d'événements. supprimer le bouton.

J'apprécierais toute l'aide que je pourrais obtenir. Merci.

Répondre

3

Si je comprends bien la question que je pense que vous serez en mesure d'obtenir la personne de DataContext

private void RemovePersonButton_Click(object sender, RoutedEventArgs e) 
{ 
    Button clickedButton = (Button)e.Source; 
    Person selectedItem = clickedButton.DataContext as Person; 
    if (selectedItem != null) 
    { 
     PersonCollection.Remove(selectedItem); 
    } 
} 

du bouton Une autre façon est de trouver la zone de liste dans le VisualTree

private void RemovePersonButton_Click(object sender, RoutedEventArgs e) 
{ 
    Button clickedButton = (Button)e.Source; 
    ListBox listBoxParent = GetVisualParent<ListBox>(clickedButton); 
    Person selectedItem = listBoxParent.SelectedItem as Person; 
    //... 
} 

public T GetVisualParent<T>(object childObject) where T : Visual 
{ 
    DependencyObject child = childObject as DependencyObject; 
    while ((child != null) && !(child is T)) 
    { 
     child = VisualTreeHelper.GetParent(child); 
    } 
    return child as T; 
} 
+0

Correct! Très bien. Je n'étais pas au courant de la propriété 'DataContext'. Pour ce qui en vaut la peine, j'ai pu trouver mon chemin dans l'arborescence des éléments en appelant la méthode 'VisualTreeHelper.GetParent (DependencyObject reference)', mais c'est une bien meilleure solution! Je vous remercie. – Boris

+0

Je préfère la première solution. Merci d'avoir posté! – Boris

+0

@Boris: Bien sûr! Oui, la première version est mieux à coup sûr :) Ajouté le second parce que je n'étais pas sûr si vous aviez besoin de la ListBox correspondante pour quelque chose –

0

Vous peut-être essayer d'utiliser VisualTreeHelper.GetParent pour parcourir l'arborescence visuelle, plutôt que de s'appuyer sur le parent logique. Cela dit, vous pouvez décider si vous pouvez envelopper votre Person dans une classe PersonItem, avec des informations de contexte supplémentaires afin que le PersonItem sache comment supprimer la Person de la liste. Je vais parfois utiliser ce modèle et j'ai écrit une classe EncapsulatingCollection qui instancie automatiquement les objets wrapper en fonction des changements dans un ObservableCollection surveillé.

+0

Merci pour votre réponse. Wrapping the Person est une idée ingénieuse, mais la solution fournie par Meleak est essentiellement tout ce dont j'ai besoin pour le moment. À votre santé. – Boris