如何使用 AdvancedCollectionView 源更新 UWP ListView 中的项目

Posted

技术标签:

【中文标题】如何使用 AdvancedCollectionView 源更新 UWP ListView 中的项目【英文标题】:How to update item in UWP ListView with AdvancedCollectionView source 【发布时间】:2020-10-22 11:22:21 【问题描述】:

我使用来自 Windows Community Toolkit 的 AdvanceCollectionView 作为 XAML ListView 的源,以允许排序和过滤。我在更新 ListView 时遇到问题。

为了重现这个问题,我创建了一个简单的Person 类。在MainPage XAML 中,我有一个ListView MyXAMLList 和一个Button EditButton。在MainPage 代码中,我有一个ObservableCollection<Person> MyPersonListAdvancedCollectionView MyPersonACV。在Page_Loaded 事件中,我将一个人添加到列表中,并使用 AdvancedCollectionView 作为列表视图的来源:

Person p = new Person

    Name = "John",
    Age = 35
;

MyPersonList.Add(p);
MyPersonACV = new AdvancedCollectionView(MyPersonList, true);
MyXAMLList.ItemsSource = MyPersonACV;    

这行得通,我可以在列表中看到 John。

EditButton 代码中,我尝试更新列表中的项目,但这不起作用。 ObservableCollection 和 AdvancedCollectionView 都已更新,但 XAML 列表仍显示旧名称“John”而不是“Mary”。

MyPersonList[0].Name = "Mary";

Debug.WriteLine(MyPersonList[0].ToString());
Debug.WriteLine(MyPersonACV[0].ToString());
        

我已尝试更新 MyXAMLList.SelectedItem,但结果相同:

Person p = (Person)MyXAMLList.SelectedItem;
p.Name = "Mary";

我也尝试添加MyPersonACV.Refresh();,但没有帮助。

我做错了什么?如何更新列表中的项目?

完整代码如下

人物类:

class Person

    public string Name get; set;
    public int Age  get; set; 
    public override string ToString()
    
        return Name;
    

主页 XAML:

<Page
    x:Class="App3.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App3"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="ThemeResource ApplicationPageBackgroundThemeBrush"
    Loaded="Page_Loaded">

    <Grid>
        <StackPanel Orientation="Vertical">
            <ListView Height="Auto" Width="Auto" x:Name="MyXAMLList" SelectionMode="Single" IsItemClickEnabled="True"/>
            <StackPanel Orientation="Horizontal">
                <Button x:Name="EditButton" Content="Edit" Click="EditButton_Click"/>
            </StackPanel>
        </StackPanel>
    </Grid>
</Page>

主页cs:

using Microsoft.Toolkit.Uwp.UI;
using System.Collections.ObjectModel;
using System.Diagnostics;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;


namespace App3


    public sealed partial class MainPage : Page
    

        private ObservableCollection<Person> MyPersonList = new ObservableCollection<Person>();
        private AdvancedCollectionView MyPersonACV;

        public MainPage()
        
            this.InitializeComponent();
        


        private void EditButton_Click(object sender, RoutedEventArgs e)
        

            //Change name
            MyPersonList[0].Name = "Mary";
            //Person p = (Person)MyXAMLList.SelectedItem;
            //p.Name = "Mary";

            Debug.WriteLine(MyPersonList[0].ToString());
            Debug.WriteLine(MyPersonACV[0].ToString());

            //MyPersonACV.Refresh();

        

        private void Page_Loaded(object sender, RoutedEventArgs e)
        
           //create person 
           Person p = new Person
           
               Name = "John",
               Age = 35
           ;
           //add to list
           MyPersonList.Add(p);
           
           //set up ListView source
           MyPersonACV = new AdvancedCollectionView(MyPersonList, true);
           MyXAMLList.ItemsSource = MyPersonACV;
        
        

    

【问题讨论】:

【参考方案1】:

我注意到你重写了ToString() 方法来显示ListView 的每一项。更新 Name 属性时,即使 Name 属性的值更新了,由于 Name 属性和 ListViewItem 没有绑定关系,并且更新数据时不会触发 ToString() 方法,所以 UI 不会更新.最好使用 DataTemplate 自定义项目的外观,将 Name 属性绑定到元素(例如 TetxBlock)并实现 INotifyPropertyChanged 接口。在这种情况下,当 Name 属性更改时,它将向绑定提供更改通知,并且 UI 将更新。例如:

.xaml:

<ListView Height="Auto" Width="Auto" x:Name="MyXAMLList" SelectionMode="Single" IsItemClickEnabled="True">
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="Binding Name"></TextBlock>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

.cs:

public class Person : INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged = delegate  ;

    private string name  get; set; 
    public string Name 
    
        get 
        
            return name;
        
        set 
        
            name = value;
            OnPropertyChanged();
        
    
    public int Age  get; set; 

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    


private void EditButton_Click(object sender, RoutedEventArgs e)

    //Change name
    MyPersonList[0].Name = "Mary";

【讨论】:

谢谢,确实有效。但是 AdvancedCollectionView 的文档说我不必使用 ObservableCollection 并且可以使用简单的通用列表。我以为 ACV 会解决这个问题? “没有必要使用例如 ObservableCollection 来使用 AdvancedCollectionView。即使在构造函数中提供一个简单的列表时,它也可以按预期工作。” (docs.microsoft.com/en-us/windows/communitytoolkit/helpers/…)

以上是关于如何使用 AdvancedCollectionView 源更新 UWP ListView 中的项目的主要内容,如果未能解决你的问题,请参考以下文章

如何使用本机反应创建登录以及如何验证会话

如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]

如何使用 AngularJS 的 ng-model 创建一个数组以及如何使用 jquery 提交?

如何使用laravel保存所有行数据每个行名或相等

如何使用 Math.Net 连接矩阵。如何使用 Math.Net 调用特定的行或列?

WSARecv 如何使用 lpOverlapped?如何手动发出事件信号?