扩展选择模式,虚拟化和IsSelected绑定

似乎在扩展选择模式下IsSelected绑定是错误的。 看起来只有选择中的最后一项超出范围才能正确处理。

示范:

使用Control选择项目098 。 当选择94 (没有控制 !)时,选择计数器应为1 ,但是你会看到3 。 向上滚动显示只有一个(最后一个)选择超出范围的项目未被选中。

以下是mcve:

XAML:

             

CS:

 public class NotifyPropertyChanged : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged([CallerMemberName] string property = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); } public class Item : NotifyPropertyChanged { bool _isSelected; public bool IsSelected { get { return _isSelected; } set { _isSelected = value; } } public string Text { get; set; } } public class ViewModel : NotifyPropertyChanged { public ObservableCollection Items { get; } public ViewModel() { var list = new List(); for (int i = 0; i < 100; i++) list.Add(new Item() { Text = i.ToString() }); Items = new ObservableCollection(list); } } public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DataContext = new ViewModel(); } void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { Title = ((ViewModel)DataContext).Items.Count(item => item.IsSelected).ToString(); } } 

快速解决方法是禁用列表控件( ListBoxListView )虚拟化:

 VirtualizingStackPanel.IsVirtualizing="False" 

问题:如何在不禁用虚拟化的情况下解决问题?

嗯,这是预期的行为。 虚拟化仅为可见项创建可视容器( ListBoxItem )。 为了使绑定起作用,容器必须首先存在,因此只有可见项受到影响。

有两个明显的解决方案:

  1. 禁用虚拟化。
  2. 请改用SelectionChanged事件。 您可以从SelectionChangedEventArgs添加和删​​除项目。 然后,您需要做的就是执行IsSelected并相应地设置IsSelected属性(您不需要迭代Items )。 Ctrl + A也可以,你只需要处理添加的项目(并完全删除绑定):

     void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { foreach (var removedItem in e.RemovedItems.Cast()) { removedItem.IsSelected = false; } foreach (var addedItem in e.AddedItems.Cast()) { addedItem.IsSelected = true; } Title = ((ViewModel) DataContext).Items.Count(item => item.IsSelected).ToString(); }