1
votes

I am using AdvanceCollectionView from Windows Community Toolkit as a source for a XAML ListView, to allow sorting and filtering. I am having problems with updating the ListView.

To replicate the issue, I've created a simple Person class. In MainPage XAML I have a ListView MyXAMLList and a Button EditButton. In the MainPage code, I have an ObservableCollection<Person> MyPersonList and AdvancedCollectionView MyPersonACV. In Page_Loaded event I add a person to the list and use AdvancedCollectionView as a source for the list view:

Person p = new Person
{
    Name = "John",
    Age = 35
};

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

This works and I can see John in the list.

In the EditButton code I try to update the item on the list but this isn't working. Both the ObservableCollection and the AdvancedCollectionView are updated, but the XAML list is still displaying the old name "John" instead of "Mary".

MyPersonList[0].Name = "Mary";

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

I've tried updating the MyXAMLList.SelectedItem instead, but the same result:

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

I've also tried adding MyPersonACV.Refresh(); but doesn't help.

What am I doing wrong? How can I update an item in the list?

Full code below

Person class:

class Person
{
    public string Name {get; set;}
    public int Age { get; set; }
    public override string ToString()
    {
        return Name;
    }
}

MainPage 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>

MainPage 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

1 Answers

1
votes

I noticed you override the ToString() method to display each item of ListView. When you update the Name property, even if the value of Name property has updated, since there is no binding relationship between Name property and ListViewItem, and the ToString() method isn't triggered when you update data, the UI isn't updated. It'sbetter to customize the appearance of items using DataTemplate, binding the Name property to the element(e.g. TetxBlock) and implement INotifyPropertyChanged interface. In this case, when the Name proeprty changes, it will provide change notifications to the binding and the UI will update. For exmaple:

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