wpf - 如何在 ListView 中为不可见(虚拟化)项目绑定(bind) IsSelected

标签 wpf virtualization ui-virtualization

我需要在 WPF 应用程序中处理大量数据。

我已将大型集合绑定(bind)到 ListView 并且我正在使用 ItemContainerStyle将列表项的 IsSelected 属性与我的对象的 IsSelected 绑定(bind)属性,以便当在 ListView 中选择项目时,我的对象'IsSelected属性也将设置为 true。通过这样做,我可以轻松地仅对列表中已选择的对象执行命令。

我在 ListView 中使用 UI 虚拟化,因为否则应用程序会很缓慢。但是因为我的整个集合中只有一个子集在列表中可见,所以当我使用 CTRL+A 选择列表中的所有项目时,只有加载的项目有它们的 IsSelected属性设置为真。不可见的项目(被虚拟化的项目)有它们的 IsSelected属性设置为假。这是一个问题,因为当我选择列表中的所有项目时,我希望 IsSelected集合中所有项目的属性设置为 true。

我创建了一些示例代码来说明问题:

主窗口.xaml

<Window x:Class="VirtualizationHelp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525" x:Name="wnd">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <Button Grid.Row="0" Content="Click me" Click="Button_Click" />
    <ListView Grid.Row="1" ItemsSource="{Binding Path=Persons, ElementName=wnd}">
        <ListView.ItemContainerStyle>
            <Style TargetType="{x:Type ListViewItem}">
                <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}"/>
            </Style>
        </ListView.ItemContainerStyle>
    </ListView>
</Grid>
</Window>

主窗口.xaml.cs
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace VirtualizationHelp
{
    public partial class MainWindow : Window
    {
        List<SelectablePerson> _persons = new List<SelectablePerson>(10000);
        public List<SelectablePerson> Persons { get { return _persons; } }
        public MainWindow()
        {
            for (int i = 0; i < 10000; i++)
            {
                SelectablePerson p = new SelectablePerson() { Name = "Person " + i, IsSelected = false };
                _persons.Add(p);
            }
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            int count = Persons.Where(p => p.IsSelected == true).Count();
            (sender as Button).Content = count.ToString();
        }
    }

    public class SelectablePerson
    {
        public string Name { get; set; }
        public bool IsSelected { get; set; }
        public override string ToString()
        {
            return Name;
        }
    }
}

单击表单顶部的按钮时,它会计算集合中“IsSelected”属性设置为 true 的项目。可以看到,当你按下 CTRL+A 选择列表中的所有项目时,它显示只选择了 19 个项目。

有人知道解决这个问题的方法吗?我不能关闭虚拟化,因为我会得到可怕的性能。

最佳答案

我认为这是你的约束力。基本上你正在更新/绑定(bind) ListViewItem,它只会更新可见的,而不是整个列表。我会玩它,现在你可以在代码绑定(bind)中解析..

<Window x:Class="VirtualizationHelp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" x:Name="wnd">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock x:Name="txtSelectedItemsCount"/>
        <ListView Grid.Row="1" ItemsSource="{Binding Path=Persons, ElementName=wnd}" 
         SelectionChanged="ListView_SelectionChanged"/>
    </Grid>
</Window>

private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var lv = (ListView) sender;
    txtSelectedItemsCount.Text = lv.SelectedItems.Count.ToString();
}

关于wpf - 如何在 ListView 中为不可见(虚拟化)项目绑定(bind) IsSelected,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7372893/

相关文章:

c# - WPF 的 Windows 资源管理器控件?

wpf - 在对虚拟化 ListView 进行分组时,如何避免 VirtualizingStackPanel.MeasureOverride 卡住?

c# - Popup 中的 UI 虚拟化

WPF : TreeView virtualization not working

c# - WebBrowser 控件基本授权标题

wpf - Windows 7 触摸屏 "Shrug"

c# - 如何将复杂的 BAML 反编译为有效的 XAML

magento - Magento 是否有现有维护良好的 Vagrant 厨师食谱?

memory-management - 虚拟内存和物理内存有什么区别?

linux - DNS 服务器在 QEMU 用户模式网络中不工作