当绑定的值发生变化时,.NET MAUI的输入框中的文本未更新

后端开发 2026-07-09

我正在尝试开发一个.NET Maui应用,用于为放疗患者进行剂量计算。
我刚起步,最初是用事件驱动的方法来开发,但后来决定还是尝试走MVVM的路径。
这是一个Windows应用。

我的问题在于,当我从导入页面返回时,患者姓名和ID的输入字段不会更新。
为了避免贴出冗长的代码,我移除了一些不必要的代码。
在内存中,我在启动时将患者姓名设为Mickey Mouse,ID设为1。
启动应用时会显示这些内容。
当我从ImportPage返回后,为了测试我手动将名字改为Peters,ID改为2,但输入字段并没有更新。
我感觉自己可能忽略了某些地方,但看不出具体是什么。
我对.NET Maui和 MVVM仍然是新手。

我的 HomePage.xaml - 在这里我把患者姓名和ID绑定到两个输入字段:

<?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"
             x:Class="Aequus.Maui.Views.HomePage"
             xmlns:controls="clr-namespace:Aequus.Maui.Views.Controls"
             xmlns:vm="clr-namespace:Aequus.Maui.ViewModels"
             x:DataType="vm:HomePageViewModel">

    <ContentPage.ToolbarItems>
        <ToolbarItem
            x:Name="ImportToolBar"
            Text="Import"
            Clicked="ImportToolBar_Clicked">
        </ToolbarItem>
    </ContentPage.ToolbarItems>

    <Grid ColumnDefinitions="370,*">
        <Grid Grid.Column="0"
              Grid.Row="0"
              RowDefinitions="300,*">
        <Grid Grid.Row="0"
              Grid.Column="0"
              ColumnDefinitions="*"
              RowDefinitions="*">
        <Grid Grid.Row="0"
              Grid.Column="0"
              Margin="20, 45, 20, 20"
              ColumnDefinitions="*,3*"
              RowDefinitions="*,*,*,*,*,*,*">
              <Label Grid.Row="0" Grid.Column="0" Text="Patient:" VerticalTextAlignment="Center"></Label>
              <Entry 
                   Grid.Row="0" Grid.Column="1" IsReadOnly="False" VerticalTextAlignment="Center" 
                   HeightRequest="30" MinimumHeightRequest="30" Text="{Binding MyPatient}">
              </Entry>

              <Label Grid.Row="1" Grid.Column="0" Text="ID:" VerticalTextAlignment="Center"></Label>
              <Entry 
                        Grid.Row="1" Grid.Column="1" IsReadOnly="False" VerticalTextAlignment="Center"
                        HeightRequest="30" MinimumHeightRequest="30" Text="{Binding MyPatient.Id}"></Entry>

        </Grid>
        </Grid>
        </Grid>
    </Grid>
</ContentPage>

我的 HomePage.xaml.cs

using Aequus.CoreBusiness;
using Aequus.Maui.ViewModels;
using Aequus.Maui.Views.Controls;
using Aequus.UseCases.Interfaces;
using DicomObjects;
using DicomObjects.Enums;

namespace Aequus.Maui.Views;

public partial class HomePage : ContentPage
{
    private readonly HomePageViewModel homePageViewModel;

    public HomePage(HomePageViewModel homePageViewModel)
    {
        InitializeComponent();
        this.homePageViewModel = homePageViewModel;

        this.BindingContext = this.homePageViewModel;
    }

    private async void ImportToolBar_Clicked(object sender, EventArgs e)
    {
        await Shell.Current.GoToAsync(nameof(ImportPage));
    }
}

我的 HomePageViewModel - 在这里我使用一个 ApplyQueryAttributes 方法来获取在子页面 (ImportPage) 中选择的Dicom图像:

using Aequus.CoreBusiness;
using Aequus.UseCases.Interfaces;
using CommunityToolkit.Mvvm.ComponentModel;
using DicomObjects;
using DicomObjects.Enums;

namespace Aequus.Maui.ViewModels
{
    public class HomePageViewModel : ObservableObject, IQueryAttributable
    {
        public Patient? MyPatient { get; set; }
        public ILoadPatientUseCase LoadPatientUseCase { get; }

        private DicomImage? currentDicomImage = null;

        public HomePageViewModel(ILoadPatientUseCase loadPatientUseCase)
        {
            LoadPatientUseCase = loadPatientUseCase;
            LoadPatientAsync();
        }

        public async Task LoadPatientAsync()
        {
            MyPatient = await LoadPatientUseCase.ExecuteAsync();  
        }

        public void ApplyQueryAttributes(IDictionary<string, object> query)
        {
            if (query.TryGetValue("ReturnedObject", out var obj))
            {
                MyPatient.Lastname = "Peters";
                MyPatient.Id = 2;

                Application.Current.MainPage.DisplayAlert("MESSAGE", MyPatient.Lastname, "OK");
            }
        }
    }
}

ImportPage.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"
             x:Class="Aequus.Maui.Views.ImportPage">

    <Grid
        RowDefinitions="50">
        <Grid
            Grid.Row="0"
            ColumnDefinitions="*,*,*">
            <Button
                x:Name="btnImport"
                Margin="10,0,10,0"
                Grid.Column="1"
                Text="Import"
                Clicked="btnImport_Clicked">
            </Button>
            <Button
                x:Name="btnCancel"
                Margin="10,0,10,0"
                Grid.Column="2"
                Text="Cancel"
                Clicked="btnCancel_Clicked">
            </Button>
        </Grid>

    </Grid>
</ContentPage>

ImportPage.xaml.cs

namespace Aequus.Maui.Views;

using DicomObjects;

public partial class ImportPage : ContentPage
{
    public DicomImage? currentDicomImage;

    public ImportPage()
    {
        InitializeComponent();
    }

    private async void btnImport_Clicked(object sender, EventArgs e)
    {
    }

    private async void btnCancel_Clicked(object sender, EventArgs e)
    {
        //Shell.Current.GoToAsync("..");
        await Shell.Current.GoToAsync($"//{nameof(HomePage)}");

        // IN CHILD PAGE
        var navigationParameter = new Dictionary<string, object>
        {
            { "ReturnedObject", currentDicomImage }
        };
        await Shell.Current.GoToAsync("..", navigationParameter);
    }
}

Patient 类:

namespace Aequus.CoreBusiness
{
    // All the code in this file is included in all platforms.
    public class Patient
    {
        public int Id { get; set; }
        public string Lastname { get; set; }
        public string Firstname { get; set; }

        public override string ToString()
        {
            return Lastname + ", " + Firstname;
        }
    }
}

解决方案

这是因为你的属性在变化时没有通知UI,原因是你的模型没有对变化进行监听,

如果你使用的是CommunityToolkit.Maui.Mvvm,你需要将你的模型改成ObservableObject

 public partial class Patient : ObservableObject
 {
     [ObservableProperty]
     public int id;

     public string Lastname { get; set; }
     public string Firstname { get; set; }

     public override string ToString()
     {
         return Lastname + ", " + Firstname;
     }
 }

对于任何需要绑定为双向属性的属性,也要类似处理。

另外我还注意到你的其中一个输入框绑定到了一个Patient对象?那样不会工作。文本是字符串,只有绑定成字符串时才会起作用。

如果你有任何问题,告诉我!

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章