我正在尝试在 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
的预期结果?
您共享的代码存在几个问题。
首先,由于您想根据属性
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>