开发者

Problem with traversing WPF element tree

开发者 https://www.devze.com 2023-01-28 10:37 出处:网络
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 p

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 lis开发者_Python百科t 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.


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


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消