VirtualizationStackPanel + MVVM + Multiple Choice

I implemented a selection template similar to the one described in this post , using ViewModel to save the IsSelected value and bind ListViewItem.IsSelected to ViewModel IsSelected:

 <ListView.ItemContainerStyle> <Style TargetType="{x:Type ListViewItem}"> <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/> </Style> </ListView.ItemContainerStyle> 

This works overall, but I ran into a serious problem. Using a VirtualizingStackPanel as a panel in a list view, only visible ListViewItem are created. If I use "Ctrl + A" to select all elements or using the "Shift + Ctrl + End" key combination in the first element, all elements are selected, but for invisible elements ViewModel does not get its IsSelected set to true. This is logical because if the ListViewItem not created, the binding cannot work.

Has anyone experienced the same problem and found a solution (other than using VirtualizingStackPanel )?

+22
listview wpf mvvm stackpanel virtualizingstackpanel
Aug 13 '09 at 18:07
source share
3 answers

I found another way to handle the selection in the MVVM template that solved my problem. Instead of saving the selection in view mode, the selection is retrieved from the ListView / ListBox and passed as a parameter to the command. Everything is done in XAML:

 <ListView x:Name="_items" ItemsSource="{Binding Items}" ... /> <Button Content="Remove Selected" Command="{Binding RemoveSelectedItemsCommand}" CommandParameter="{Binding ElementName=_items, Path=SelectedItems}"/> 

in my ViewModel model:

 private void RemoveSelection(object parameter) { IList selection = (IList)parameter; ... } 
+28
Aug 13 '09 at 19:43
source share

In my case, I decided to solve this by deriving the ListBoxEx class from the ListBox and adding code to respond to the selection changes, ensuring that the selection state was respected on the item view models:

 private readonly List<IListItemViewModelBase> selectedItems = new List<IListItemViewModelBase>(); protected override void OnSelectionChanged(SelectionChangedEventArgs e) { base.OnSelectionChanged(e); bool isVirtualizing = VirtualizingStackPanel.GetIsVirtualizing(this); bool isMultiSelect = (SelectionMode != SelectionMode.Single); if (isVirtualizing && isMultiSelect) { var newSelectedItems = SelectedItems.Cast<IListItemViewModelBase>(); foreach (var deselectedItem in this.selectedItems.Except(newSelectedItems)) { deselectedItem.IsSelected = false; } this.selectedItems.Clear(); this.selectedItems.AddRange(newSelectedItems); foreach (var newlySelectedItem in this.selectedItems) { newlySelectedItem.IsSelected = true; } } } 
+3
Nov 12 '09 at 15:50
source share

Besides using VirtualizingStackPanel , the only thing I can think of is to capture these keyboard shortcuts and methods to change a specific range of your ViewModel elements so that their IsSelected property is set to True > (e.g. SelectAll() , SelectFromCurrentToEnd() ). Basically, a Binding bypass on a ListViewItem to control selection for such cases.

+1
Aug 13 '09 at 19:08
source share



All Articles