首页 > 解决方案 > UWP ListView的SelectedItem在ListView在其他ListView大数据时被重置

问题描述

当大ListView 的DataTemplate 包含小ListView 时,小ListView 的SelectedItem 会被重置。
我制作了示例应用程序,从三个选项中选择每个人的国家。我从后面的代码中选择了最后一个小 ListView 项目(索引:999)的“印度”。
但是当我向下滚动时,没有选择任何内容,调试日志如下。

[调试日志]

添加:印度,删除:

添加:,删除:印度

[主页.xaml]

<ListView ItemsSource="{x:Bind People}" SelectionMode="None">
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="local:Person">
            <StackPanel BorderBrush="Black" BorderThickness="0,0,0,1">
                <TextBlock Text="{x:Bind Country, Mode=OneWay}"/>
                <ListView x:Name="CountryList"
                            ItemsSource="{x:Bind Countries, Mode=OneWay}"
                            SelectedItem="{x:Bind Country, Mode=TwoWay}"
                            SelectionChanged="CountryList_SelectionChanged">
                </ListView>
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

[MainPage.xaml.cs]

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    GenerateSampleData();
}

private void GenerateSampleData()
{
    for (int i = 0; i < 1000; i++)
    {
        People.Add(new Person
        {
            Countries = new List<string> { "China", "India", "USA" },
        });
    }
    People[999].Country = "India";
}

private void CountryList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    StringBuilder sb = new StringBuilder("Added:");
    foreach (var added in e.AddedItems)
    {
        if (added is string country)
        {
            sb.Append($" {country,-5}");
        }
    }

    sb.Append(", Removed:");
    foreach (var removed in e.RemovedItems)
    {
        if (removed is string country)
        {
            sb.Append($" {country,-5}");
        }
    }
    Debug.WriteLine(sb);
}

完整来源如下。
https://github.com/tokane888/ListViewQuestion

而且我不确定它是否相关,但一些小的 ListView 显示为灰色,如下所示。
(即使是通过代码或手动操作,我也没有接触过这个小 ListView。)
灰名单视图

标签: c#listviewuwp

解决方案


  1. ListView您的项目未被选中的原因是您在ListView实际加载之前设置了您的属性。最好在ListView Loaded事件中设置选定的项目。

  2. 您看到的灰色区域是由于ListView虚拟化,因为您ListView包含大量数据。

为了解决这两个问题,请修改您的代码如下:

XAML:

<ListView ItemsSource="{x:Bind People}" SelectionMode="None">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:Person">
                    <StackPanel BorderBrush="Black" BorderThickness="0,0,0,1">
                        <TextBlock Text="{x:Bind Country, Mode=OneWay}"/>
                        <ListView x:Name="CountryList"
                                    ItemsSource="{x:Bind Countries, Mode=OneWay}"
                                    SelectedItem="{x:Bind Country, Mode=TwoWay}"
                                    SelectionChanged="CountryList_SelectionChanged"
                                    Loaded="CountryList_Loaded"
                                  >
                            <ListView.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <VirtualizingStackPanel/>
                                </ItemsPanelTemplate>
                            </ListView.ItemsPanel>
                        </ListView>

                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
</ListView>

后面的代码:

 public sealed partial class MainPage : Page
    {
        public ObservableCollection<Person> People { get; } = new ObservableCollection<Person>();

        public MainPage()
        {
            this.InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            GenerateSampleData();
        }

        private void GenerateSampleData()
        {
            for (int i = 0; i < 1000; i++)
            {
                People.Add(new Person
                {
                    Countries = new List<string> { "China", "India", "USA" },
                });
            }

        }

        private void CountryList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            StringBuilder sb = new StringBuilder("Added:");
            foreach (var added in e.AddedItems)
            {
                if (added is string country)
                {
                    sb.Append($" {country,-5}");
                }
            }

            sb.Append(", Removed:");
            foreach (var removed in e.RemovedItems)
            {
                if (removed is string country)
                {
                    sb.Append($" {country,-5}");
                }
            }
            Debug.WriteLine(sb);
        }

        private void CountryList_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
           People[999].Country = "India";
        }
    }

另请参阅帖子以获取详细信息。


推荐阅读