28

我已经实现了一种类似于这篇文章中描述的选择模式,使用 ViewModel 来存储 IsSelected 值,并将其绑定ListViewItem.IsSelected到 ViewModel IsSelected:

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

它通常有效,但我遇到了一个严重的问题。通过使用 aVirtualizingStackPanel作为列表视图中的面板,只会创建可见ListViewItem的。如果我使用“Ctrl+A”选择所有项目,或者通过在第一个项目上使用“Shift+Ctrl+End”等快捷键组合,所有项目都会被选中,但对于不可见项目,ViewModel 不会获得其 IsSelected设置为真。这是合乎逻辑的,因为如果ListViewItem没有创建,绑定将无法工作。

有没有人遇到过同样的问题,并找到了解决方案(除了不使用 a VirtualizingStackPanel)?

4

3 回答 3

32

我在 MVVM 模式中找到了另一种处理选择的方法,它解决了我的问题。不是在视图模型中维护选择,而是从 ListView/ListBox 检索选择,并作为参数传递给命令。全部在 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;
    ...
}
于 2009-08-13T19:43:48.130 回答
6

就我而言,我最终通过从 ListBox 派生 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;
        }
    }
}
于 2009-11-12T15:50:58.983 回答
1

除了不使用 之外VirtualizingStackPanel,我唯一能想到的就是捕获那些键盘快捷键并具有修改特定范围ViewModel项目的方法,以便将它们的IsSelected属性设置为True(例如SelectAll(),,SelectFromCurrentToEnd())。基本上绕过BindingonListViewItem来控制此类情况的选择。

于 2009-08-13T19:08:13.580 回答