Question

I have a ListBox data bound to the collection of my PersonCollection class. Next, I have defined a data template for objects of type Person, consisted of a DockPanel which contains a TextBlock for a person's name and a Button to remove the person from the list. It looks very nice all together.

The problem I am facing is that I am unable to reach the selected item (and delete it) in the list box when I click the button defined in the data template. Here's the handler of the button:

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

The last created object control is null, i.e. I cannot progress further up the element tree, so I cannot reach the list and its SelectedItem. Important thing to note here is that cannot simply go with getting the selected item from the list by calling it, because I have more than one list in the window and all those lists implement the same data template, i.e. share the same event handler for the delete button.

I would appreciate all the help I could get. Thanks.

Was it helpful?

Solution

If I understand the question correctly I think you'll be able to get the Person from the Button's 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);
    }
}

Another way is to find the ListBox in the 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;
}

OTHER TIPS

You might try using VisualTreeHelper.GetParent to walk the visual tree, rather than relying on the Logical Parent.

That said, you might consider whether you can wrap your Person in a PersonItem class, with additional context information so that the PersonItem knows how to remove the Person from the list. I'll sometimes use this pattern and I wrote an EncapsulatingCollection class that automatically instantiates wrapper objects based on the changes in a monitored ObservableCollection.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top