Home > Back-end >  .net maui Cannot get updated fields in an Observable collection to update in bound collection view
.net maui Cannot get updated fields in an Observable collection to update in bound collection view

Time:06-15

I'm trying to update actual fields in an ObservableCollection that is bound to a CollectionView.

The CollectionView updates fine on adding, removing items, but not if I programmatically change an item in the list.

I understand from this post Observable collection not updated that I need to implement INotifyPropertyChanged.

I am using the CommunityToolkit.Mvvm and had hoped that this kind of magic would be automatically done, but it appears not. I don't have the C# knowledge to know how to do what I want. Could someone help me please :)

There is a repo at https://github.com/gfmoore/TestCollectionBinding

and here is my current code:

Views.MyItem.cs


namespace TestCollectionBinding.Views;

public class MyItem
{
  public string Name { get; set; }
  public string Device { get; set; }
}

ViewModels.MainPageViewModel.cs

using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using TestCollectionBinding.Views;

namespace TestCollectionBinding.ViewModels;

public partial class MainPageViewModel : ObservableObject
{
  [ObservableProperty]
  public ObservableCollection<MyItem> myItems = new()
  {
    new MyItem
    {
      Name = "Heart Rate Monitor",
      Device = "12:12:12:12:AB"
    },

    new MyItem
    {
      Name = "Cadence",
      Device = "34:34:34:34:CD"
    }
  };

  //show details
  public ICommand ChangeCommand => new Command(ChangeControl);
  public void ChangeControl()
  {
    //change device
    foreach (MyItem q in MyItems)
    {
      q.Device = "***********";
    }
    Console.WriteLine($"Change device");
  }
}

and the MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:TestCollectionBinding.ViewModels"
             x:Class="TestCollectionBinding.MainPage">

  <ContentPage.BindingContext>
    <local:MainPageViewModel />
  </ContentPage.BindingContext>

  <StackLayout>
    <Label Text="Items" 
           FontSize="20"
           TextColor="Blue"/>

    <CollectionView x:Name="MyItemsList"
                    ItemsSource="{Binding MyItems}">
      <CollectionView.ItemTemplate>
        <DataTemplate>
          <Grid
            Margin="10, 0, 10, 10"
            ColumnDefinitions="200, 200">
            <Label Grid.Column="0" 
                   Text="{Binding Name}" 
                   FontSize="20"/>

            <Label Grid.Column="1" 
                   Text="{Binding Device}" 
                   FontSize="20"/>            
          </Grid>
   
        </DataTemplate>
      </CollectionView.ItemTemplate>
    </CollectionView>

    <Button
      Text="Change device names"
      FontFamily="20"
      WidthRequest="150"
      Command="{Binding ChangeCommand}" />
    
  </StackLayout>

</ContentPage>

So the MainPage displays two items in the list and when I hit the button the command cycles through the list and just replaces the Device property with "*********".

I expect to see these changes in the displayed list.

Oh for the days of ... dBase II lol

G

CodePudding user response:

from the docs

public class MyItem : ObservableObject
{
    private string name;

    public string Name
    {
        get => name;
        set => SetProperty(ref name, value);
    }
}

CodePudding user response:

Following the helpful hint from @Jason (ta) I searched a bit harder and found this amazingly helpful explanation at the source: https://docs.microsoft.com/en-us/windows/communitytoolkit/mvvm/observableobject

My MyItem.cs now looks like:

public partial class MyItem : ObservableObject
{
  private string name;
  private string device;

  public string Name { 
    get => name; 
    set => SetProperty(ref name, value); 
  }

  public string Device { 
    get => device; 
    set => SetProperty(ref device, value); 
  }
}

It's more complex than I expected it to look... I have to ask though, why is this stuff so impenetrable, I thought coding was supposed to get easier over the years? I would have expected that if a device is connected to a list then it should just (magically) work without all the plumbing that should be hidden from view. If you don't want anything to change make it readonly! :sigh. One day when I'm dead and buried...

  • Related