Неправильный выбор в ListBox с VirtualizationMode="Recycling" и SeclectionMode="Extended"?
У меня действительно странное поведение. У меня есть ListBox в представлении с DataTemplate для его элементов, включая ViewModels. Я привязываю IsSelected к моей ViewModel и использую SelectionMode="Extended". Все отлично работает НО, если я добавлю VirtualiuationMode="Recycling", я получу неправильные предметы. Для воспроизведения: выделите элементы с помощью Ctrl, затем прокрутите вниз и выберите только один элемент. Нормальное поведение отменяет выбор всех элементов и просто выбирает последний без удержанного Ctrl. Но если я проверю свою ViewModel, все старые элементы будут выбраны!?!
<Grid>
<StackPanel>
<ListBox ItemsSource="{Binding People}" MaxHeight="100"
SelectionMode="Extended"
VirtualizationMode="Recycling">
<!--VirtualizingStackPanel.IsVirtualizing="True">-->
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<views:PeopleView />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Click="Button_Click">
OK
</Button>
</StackPanel>
</Grid>
Шаблон элемента
<UserControl x:Class="WpfApplication1.View.PeopleView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="Auto" Width="Auto">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="A"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="B"/>
</Grid.ColumnDefinitions>
<TextBox Text="{Binding Path=Name}"
Name="tbx_Name"
Grid.Column="0"/>
<CheckBox IsChecked="{Binding Path=IstAktiv}"
Name="cbx_IstAktiv"
Grid.Column="1"/>
</Grid>
Любая идея?
2 ответа
Я нашел обходной путь, но почему я должен изменить его "вручную" в событии изменения, а не с помощью привязки данных?
private void Lbx_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox lbx = (ListBox)sender;
foreach (PersonViewModel item in lbx.Items)
{
item.IsSelected = lbx.SelectedItems.Contains(item);
}
}
Другой вариант, связанный с более ранним ответом KCT, заключается в использовании AddedItems
а также RemovedItems
от SelectionChangedEventArgs
и нацелить изменения, такие как:
private void Lbx_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
foreach (var item in e.AddedItems)
{
((PersonViewModel)item).IsSelected = true;
}
foreach (var item in e.RemovedItems)
{
((PersonViewModel)item).IsSelected = false;
}
}
Это может повысить производительность при работе с большими коллекциями (у меня есть около 15 000 записей на панели виртуализации плитки в ListBox).