似乎在扩展选择模式IsSelected
绑定是错误的。看起来只有选择中的最后一项超出范围才能正确处理。
演示:
使用 Control 选择项0
,1
,2
和98
,97
,96
。选择94
(不使用 Control !)时,选择计数器应为1
,但您会看到3
。向上滚动显示只有一个(最后一个)选择超出范围的项目未被选中。
以下是mcve:
XAML:
<ListBox ItemsSource="{Binding Items}" SelectionMode="Extended" SelectionChanged="ListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}" />
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
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<Item> Items { get; }
public ViewModel()
{
var list = new List<Item>();
for (int i = 0; i < 100; i++)
list.Add(new Item() { Text = i.ToString() });
Items = new ObservableCollection<Item>(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"
问题:如何在不禁用虚拟化的情况下解决问题?
答案 0 :(得分:3)
嗯,这是预期的行为。虚拟化仅为可见项创建可视容器(ListBoxItem
)。为了使绑定起作用,容器必须首先存在,因此只有可见项受到影响。
有两个明显的解决方案:
请改用SelectionChanged
事件。您可以从SelectionChangedEventArgs
添加和删除项目。然后,您需要做的就是执行强制转换并相应地设置IsSelected
属性(您不需要迭代Items
)。 Ctrl + A也可以,你只需要处理添加的项目(并完全删除绑定):
void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
foreach (var removedItem in e.RemovedItems.Cast<Item>())
{
removedItem.IsSelected = false;
}
foreach (var addedItem in e.AddedItems.Cast<Item>())
{
addedItem.IsSelected = true;
}
Title = ((ViewModel) DataContext).Items.Count(item => item.IsSelected).ToString();
}