.net maui 无法获取 Observable 集合中的更新字段以在绑定集合视图中更新

问题描述 投票:0回答:4

我正在尝试更新绑定到 CollectionView 的 ObservableCollection 中的实际字段。

CollectionView 在添加、删除项目时更新得很好,但如果我以编程方式更改列表中的项目则不会。

我从这篇文章Observable集合未更新中了解到我需要实现INotifyPropertyChanged。

我正在使用 CommunityToolkit.Mvvm,并希望这种魔法能够自动完成,但似乎没有。我没有 C# 知识,不知道如何做我想做的事。有人可以帮我吗:)

有一个存储库位于 https://github.com/gfmoore/TestCollectionBinding

这是我当前的代码:

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

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

因此,MainPage 在列表中显示两个项目,当我点击按钮时,命令会循环浏览列表,并将 Device 属性替换为“*********”。

我希望在显示的列表中看到这些更改。

哦,对于...dBase II 的日子,哈哈

G

.net observablecollection maui
4个回答
6
投票

来自文档

public class MyItem : ObservableObject
{
    private string name;

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

6
投票

我只是想知道为什么我的列表在以编程方式更新后没有更新。我发现(至少对我来说)更简单的方法是按如下方式配置它,同时使用 Microsoft 的 CommunityToolkit。对于模型,让类继承自“ObservableObject”。然后用“[ObservableProperty]”标记该属性。

namespace TestCollectionBinding.Views;

public partial class MyItem : ObservableObject
{
[ObservableProperty]  
string name;
[ObservableProperty]
string device;
}

在您的 ViewModel“ViewModels.MainPageViewModel.cs”上,设置要显示的集合,如下所示。对于其他不太了解的人,不要使用“List myItems”,而是将其设置为“ObservableCollection myItems”,因为这不会以编程方式更新。我希望有人能解释为什么列表没有更新,尽管是由 OnPropertyChanged("ListName") 提出的。

[ObservableProperty]
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"
    }
  };

您需要配置 VIEW 以使用“MainPage.xaml”上的 CommunityToolkit。我添加了对: xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"

的引用
<?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"
      xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
      x:Class="TestCollectionBinding.MainPage">

我花了一整天的时间试图找出为什么我的列表没有更新视图。我想我会为其他偶然发现这个问题的人发布一个解决方案。总之,用“[ObservableProperty]”标记模型属性。在 VIEWMODEL 中利用“ObservableProperty”。然后确保 VIEW 设置为使用 Microsoft 的 CommunityToolkit,您可以从 Github 获取该工具包。

使管道更加清洁。


2
投票

按照@Jason(ta)的有用提示,我进行了一些搜索,并在源代码中发现了这个非常有用的解释:https://learn.microsoft.com/en-us/windows/communitytoolkit/mvvm/observableobject

我的 MyItem.cs 现在看起来像:

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); 
  }
}

它比我想象的要复杂...... 但我不得不问,为什么这些东西如此难以理解,我认为这些年来编码应该变得更容易?我本以为,如果一个设备连接到一个列表,那么它应该(神奇地)工作,而不需要隐藏所有的管道。如果您不想更改任何内容,请将其设为只读! :叹。有一天,当我死了并被埋葬时...


0
投票

虽然您可以按照其他贡献者的建议观察项目属性,但另一种解决方案是声明一个相同类型的新 Observable 集合,根据需要处理原始集合,将每个处理后的项目添加到新集合中,然后将其分配给原始集合收藏。这应该可以毫无问题地保持 UI 更新。例如:

[ObservableProperty]
public ObservableCollection<MyItem> myItems = new();

[RelayCommand]
async Task ButtonClickCommand() {
  var SecondCollection = new ObservableCollection<MyItem>();

  foreach (var q in MyItems)
  {
      // Process item and add to second collection
  }
  
  // Assign the second collection to the original one
  MyItems = SecondCollection;
}

仅在有限数量的项目上进行测试。

© www.soinside.com 2019 - 2024. All rights reserved.