Search code examples
c#wpfxamllistviewlistviewitem

Remove ListItem from nested ListView on Button Click


I have a nested Listbox (collection of objects in the main object list) that needs to delete the underlying items.
When the item is removed, I could reset the ItemsSource of the main list, but the main list will have tons of items and each time a item is removed from its underlying collection the main scrollbar would be also reset, making users willing to kill me in a very painful way.
My question: How can i find the container of the item which button has been clicked and how can i find the item itself so i can kill the @&!$*&#$@ (cursing onomatopoeia)?
Here's the XAML exemple of my lists:

<ListView Name="mainList">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Column 1" />
            <GridViewColumn Header="Column 2" />
            <GridViewColumn Header="Column 3" />
            <GridViewColumn Header="Collection column">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <ListBox ItemsSource="{Binding BindingCollectionProperty}">
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <Grid>
                                        <TextBlock Grid.Column="0" Text="{Binding Item.Property}" />
                                        <TextBlock Grid.Column="1" Text="{Binding Item.AnotherProperty}" />
                                        <Button Content="remove" Grid.Column="2" Click="DeleteClickEvent" />
                                    </Grid>
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>

How's my DeleteClickEvent(object sender, RoutedEventArgs e) should be like?


Solution

  • You could have a command and pass it your item as parameter instead of a click handler:

    <Button ... Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type YOURCUSTOMCONTROL}}, Path=DataContext.YOURCOMMAND}"
                CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" />
    

    If you want to keep your event handler you could use VisualTreeHelper.GetParent twice on the sender.

    ListBoxItem item = VisualTreeHelper.GetParent(VisualTreeHelper.GetParent((DependencyObject)sender)) As ListBoxItem;
    
    BindingCollectionProperty.Remove(item);