VirtualizingStackPanel + MVVM +多重选择
-
16-09-2019 - |
题
我已经实现类似于此帖子使用一个ViewModel存储IsSelected值,并且由ListViewItem.IsSelected
结合视图模型IsSelected:
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
</Style>
</ListView.ItemContainerStyle>
它的工作原理一般,但我遇到的一个严重问题。通过使用一个VirtualizingStackPanel
在列表视图中的面板上,仅可见ListViewItem
越来越创建。如果我用“Ctrl + A”选中所有项目,或者使用快捷键组合中的第一项,例如“SHIFT + CTRL + END”,所有的项目都被选择,但是对于非可见项,视图模型没有得到它的IsSelected设置为true。即逻辑的,因为如果不创建ListViewItem
,结合不能工作。
任何人(从没有使用VirtualizingStackPanel
开)经历了同样的问题,并发现了一个解决方案?
解决方案
我发现在MVVM模式,它解决了我的问题的处理选择另一种方式。相反,保持在视图模型的选择,选择从ListView控件/列表框检索,并将其作为参数的命令通过。在所有XAML完成:
<ListView
x:Name="_items"
ItemsSource="{Binding Items}" ... />
<Button
Content="Remove Selected"
Command="{Binding RemoveSelectedItemsCommand}"
CommandParameter="{Binding ElementName=_items, Path=SelectedItems}"/>
在我的视图模型:
private void RemoveSelection(object parameter)
{
IList selection = (IList)parameter;
...
}
其他提示
在我的情况下,我结束了通过导出从列表框一个ListBoxEx类,并添加代码以选择变化作出反应,执行关于该项目视图模型的选择状态解决这一:
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;
}
}
}
除了不使用VirtualizingStackPanel
,我能想到的唯一的事情就是要捕捉那些键盘快捷键和有让自己ViewModel
属性设置为IsSelected
修改一定范围内的True
项目的方法(例如,SelectAll()
,SelectFromCurrentToEnd()
) 。基本上绕过上Binding
的ListViewItem
用于控制这种情况下的选择。
不隶属于 StackOverflow