扩展选择模式,虚拟化和IsSelected绑定
似乎在扩展选择模式下IsSelected
绑定是错误的。 看起来只有选择中的最后一项超出范围才能正确处理。
示范:
使用Control选择项目0
和98
。 当选择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(); } }
快速解决方法是禁用列表控件( ListBox
或ListView
)虚拟化:
VirtualizingStackPanel.IsVirtualizing="False"
问题:如何在不禁用虚拟化的情况下解决问题?
嗯,这是预期的行为。 虚拟化仅为可见项创建可视容器( ListBoxItem
)。 为了使绑定起作用,容器必须首先存在,因此只有可见项受到影响。
有两个明显的解决方案:
- 禁用虚拟化。
-
请改用
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(); }