Maui MVVM - NotifyPropertyChangedFor 不使用复杂对象及其子属性

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

我正在尝试在 MAUI 8 项目中使用

CommunityToolkit.MVVM
。我在使用
NotifyPropertyChangedFor
进行通知时遇到困难。

ViewModel 有一个布尔变量

CanSubmitForm
,它仅在 VM 出现时(在我的 API 调用完成之前)开始时获得作用域,而不是在其之后。我用
NotifyPropertyChangedFor
装饰了一个复杂的对象,并且该对象在 API 返回值后被填充。我尝试在填充
StudentInfo
及其子对象并满足 Gradconditions(子对象)后启用该按钮:

复杂的物体看起来像:

型号:

public class StudentInfo
{
    public string Id {get; set;}
    public string? StudentName {get; set;}
    public string StudentAddress {get; set;}
    public List<Checks>? Gradconditions {get; set;}
}

在我的 ViewModel 中,我有以下属性:

视图模型:

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(CanSubmitForm))]
private StudentInfo? student;

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(CanSubmitForm))]
private int conditionsMet;

我还有一个布尔变量来启用/禁用表单提交按钮:

public bool CanSubmitForm
{
    get => ConditionsMet == Student.Gradconditions.Count;
}

然后我有一个提交表单的方法:

[RelayCommand(CanExecute = nameof(CanSubmitForm))]
private void SubmitForm()
{
    /*Do housekeeping and submit form*/
}

在页面加载方法中,我通过 API 调用填充复杂

StudentInfo
对象上的所有字段,然后如果满足
CanSubmitForm
中的条件,我将启用表单提交按钮。

public async Task OnAppearingAsync(string studentId)
{
    /* populate StudentInfo object and ConditionsMet from API */

}

在页面上,我有这样的按钮:

查看:

<Button 
    Text = "Submit"
    Command="{Binding SubmitFormCommand}"
/>

我做错了什么?我怀疑我无法对子对象执行

NotifyPropertyChangedFor
并将它们传播到具有装饰的父对象。如何在子对象(一个列表)的计数上达到
NotifyPropertyChangedFor
的预期结果?

c# mvvm maui community-toolkit-mvvm
1个回答
0
投票

您共享的代码存在几个问题。

首先,由于您想根据属性

Submit
的值启用按钮(
CanSubmitForm
),因此需要为属性
ObservableProperty
添加
NotifyCanExecuteChangedFor
CanSubmitForm

    [ObservableProperty]
    [NotifyCanExecuteChangedFor(nameof(SubmitFormCommand))]
    public bool canSubmitForm = false;

其次,如果我们向属性

public List<Checks>? Gradconditions {get; set;}
添加一些项目,我们无法仅使用以下代码通知视图模型中的属性
Student
,即使您将其定义为
public ObservableCollection<string>? radconditions = new ObservableCollection<string>();

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(CanSubmitForm))]
private StudentInfo? student;

根据您的代码,我创建了一个演示并尝试实现基本功能。

我添加了另一个

Button
来向
Radconditions
添加一些假数据来模拟这种场景。

您可以参考以下代码:

public partial class MyViewModel : ObservableObject
{
    [ObservableProperty]
    [NotifyPropertyChangedFor(nameof(CanSubmitForm))]
    private StudentInfo? student = new StudentInfo();

    [ObservableProperty]
    [NotifyPropertyChangedFor(nameof(CanSubmitForm))]
    private int conditionsMet = 2;


    [ObservableProperty]
    [NotifyCanExecuteChangedFor(nameof(SubmitFormCommand))]
    public bool canSubmitForm = false;

    //public bool CanSubmitForm
    //{
    //    get => ConditionsMet == Student.Gradconditions.Count;
    //}


    [RelayCommand(CanExecute = nameof(CanSubmitForm))]
    private void SubmitForm()
    {
        /*Do housekeeping and submit form*/

    }
    [RelayCommand]
    private void AddItems() {

        Student.Gradconditions.Add("1");
        Student.Gradconditions.Add("2");

        if (Student.Gradconditions.Count == ConditionsMet) {

            CanSubmitForm = true;

        }else
        {
            CanSubmitForm = false;
        }

    }
}

学生信息.cs

public partial class StudentInfo : ObservableObject
{
    public string Id { get; set; }
    public string? StudentName { get; set; }
    public string StudentAddress { get; set; }

    [ObservableProperty]       
    public ObservableCollection<string>? gradconditions = new ObservableCollection<string>();

    //public List<string>? Gradconditions { get; set; } =new List<string>();
}

使用示例:

<?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:vm="clr-namespace:MauiApp323.ViewModels"
             x:Class="MauiApp323.MainPage">
    <ContentPage.BindingContext>
        <vm:MyViewModel></vm:MyViewModel>
    </ContentPage.BindingContext>

    <VerticalStackLayout
            Padding="30,0"
            Spacing="25">

            <Button  Text = "Submit" Command="{Binding SubmitFormCommand}"/>

            <Button Text="add data to list" Command="{Binding AddItemsCommand}"/>

    </VerticalStackLayout>
</ContentPage>
© www.soinside.com 2019 - 2024. All rights reserved.