ListBox中的选择错误,VirtualizationMode =“Recycling”和SeclectionMode =“Extended”?

时间:2010-05-28 13:02:20

标签: wpf listbox virtualization recycle

我有一种非常暴躁的行为。我在View中有一个带有DataTemplate的ListBox,用于包括ViewModels在内的项目。我将IsSelected绑定到我的ViewModel并使用SelectionMode =“Extended”。一切正常。 但如果我添加VirtualiuationMode =“回收”,我得到错误的项目。 要重现:使用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 个答案:

答案 0 :(得分:1)

我有一个解决方法,但为什么我必须在更改事件中“手动”更改它而不是通过数据绑定?

    private void Lbx_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        ListBox lbx = (ListBox)sender;
        foreach (PersonViewModel item in lbx.Items)
        {
            item.IsSelected = lbx.SelectedItems.Contains(item);
        }
    }

答案 1 :(得分:1)

与KCT早期答案相关的另一个选项是使用AddedItems中的RemovedItemsSelectionChangedEventArgs并定位更改,例如:

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;
    }
}

这可能会在更大的集合中提供更好的性能(我在ListBox的虚拟化平铺面板中有大约15,000个条目)。