如何使用 AdvancedCollectionView 源更新 UWP ListView 中的项目
How to update item in UWP ListView with AdvancedCollectionView source
我正在使用 Windows 社区工具包中的 AdvanceCollectionView 作为 XAML ListView 的来源,以允许排序和过滤。我在更新 ListView 时遇到问题。
为了重现这个问题,我创建了一个简单的 Person
class。在 MainPage
XAML 中,我有一个 ListView MyXAMLList
和一个 Button EditButton
。在 MainPage
代码中,我有一个 ObservableCollection<Person> MyPersonList
和 AdvancedCollectionView MyPersonACV
。在 Page_Loaded
事件中,我将一个人添加到列表中并使用 AdvancedCollectionView 作为列表视图的来源:
Person p = new Person
{
Name = "John",
Age = 35
};
MyPersonList.Add(p);
MyPersonACV = new AdvancedCollectionView(MyPersonList, true);
MyXAMLList.ItemsSource = MyPersonACV;
这行得通,我可以在列表中看到约翰。
在 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:
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;
}
}
}
我注意到您覆盖了 ToString()
方法来显示 ListView 的每个项目。更新Name属性时,即使Name属性的值更新了,因为Name属性和ListViewItem之间没有绑定关系,ToString()方法也没有更新数据时触发,UI 未更新。最好使用 DataTemplate 自定义项目的外观,将名称 属性 绑定到元素(例如 TetxBlock)并实现 INotifyPropertyChanged界面。在这种情况下,当 Name proeprty 更改时,它将向绑定提供更改通知并且 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";
}
我正在使用 Windows 社区工具包中的 AdvanceCollectionView 作为 XAML ListView 的来源,以允许排序和过滤。我在更新 ListView 时遇到问题。
为了重现这个问题,我创建了一个简单的 Person
class。在 MainPage
XAML 中,我有一个 ListView MyXAMLList
和一个 Button EditButton
。在 MainPage
代码中,我有一个 ObservableCollection<Person> MyPersonList
和 AdvancedCollectionView MyPersonACV
。在 Page_Loaded
事件中,我将一个人添加到列表中并使用 AdvancedCollectionView 作为列表视图的来源:
Person p = new Person
{
Name = "John",
Age = 35
};
MyPersonList.Add(p);
MyPersonACV = new AdvancedCollectionView(MyPersonList, true);
MyXAMLList.ItemsSource = MyPersonACV;
这行得通,我可以在列表中看到约翰。
在 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:
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;
}
}
}
我注意到您覆盖了 ToString()
方法来显示 ListView 的每个项目。更新Name属性时,即使Name属性的值更新了,因为Name属性和ListViewItem之间没有绑定关系,ToString()方法也没有更新数据时触发,UI 未更新。最好使用 DataTemplate 自定义项目的外观,将名称 属性 绑定到元素(例如 TetxBlock)并实现 INotifyPropertyChanged界面。在这种情况下,当 Name proeprty 更改时,它将向绑定提供更改通知并且 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";
}