VirtualizingStackPanel + MVVM + multiple selection

后端 未结 3 736
太阳男子
太阳男子 2020-11-28 05:13

I have implemented a selection pattern similar to the one described in this post using a ViewModel to store the IsSelected value, and by binding the ListViewItem.IsSel

相关标签:
3条回答
  • 2020-11-28 05:43

    In my case, I ended up solving this by deriving a ListBoxEx class from ListBox, and adding code to respond to selection changes, enforcing the selection state 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;
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-28 05:45

    Apart from not using VirtualizingStackPanel, the only thing I can think of is to capture those keyboard shortcuts and have methods for modifying a certain range of your ViewModel items so that their IsSelected property is set to True (e.g., SelectAll(), SelectFromCurrentToEnd()). Basically bypassing the Binding on ListViewItem for controlling the selection for such cases.

    0 讨论(0)
  • 2020-11-28 05:48

    I found another way of handling selection in the MVVM pattern, which solved my issue. Instead of maintaining the selection in the viewmodel, the selection is retrieved from the ListView/ListBox, and passed as a parameter to the Command. All 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:

    private void RemoveSelection(object parameter)
    {
        IList selection = (IList)parameter;
        ...
    }
    
    0 讨论(0)
提交回复
热议问题