MAUI中更新Order对象并传参至页面时对象为空的问题排查
问题分析与解决方案
你的问题核心有两个:一是Continue命令接收的Order对象为空,二是输入控件的值无法同步到Order对象。以下是具体原因和修复步骤:
核心问题原因
Order类未实现属性变更通知:MAUI的双向绑定依赖INotifyPropertyChanged接口,缺少它会导致UI输入无法同步到对象属性。- ViewModel未持有
Order实例:你的ViewModel没有公开可绑定的Order属性,UI无法找到正确的数据源。 - XAML绑定路径错误:
- 内部
VerticalStackLayout设置了x:DataType="model:Order",但它的BindingContext继承自页面的ViewModel,导致绑定路径失效。 - Button的
CommandParameter试图通过AncestorType查找Order对象,而Order是数据模型而非可视化元素,无法被找到,因此参数为空。
- 内部
修复步骤
1. 让Order类实现INotifyPropertyChanged
using System.ComponentModel; using System.Runtime.CompilerServices; namespace Pension.Models { public class Order : INotifyPropertyChanged { private DateTime _dateStart; public DateTime DateStart { get => _dateStart; set { if (_dateStart != value) { _dateStart = value; OnPropertyChanged(); } } } private DateTime _dateEnd; public DateTime DateEnd { get => _dateEnd; set { if (_dateEnd != value) { _dateEnd = value; OnPropertyChanged(); } } } private string _dogName; public string DogName { get => _dogName; set { if (_dogName != value) { _dogName = value; OnPropertyChanged(); } } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }
2. 更新ViewModel,添加可绑定的Order属性
假设你的ViewModel继承自CommunityToolkit.Mvvm的ObservableObject:
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Pension.Models; using System.Collections.Generic; namespace Pension.ViewsModels { public partial class MainViewModel : ObservableObject { // 自动生成属性变更通知的Order实例 [ObservableProperty] private Order _currentOrder = new Order(); [RelayCommand] async Task Continue(Order order) { await Shell.Current.GoToAsync(nameof(ShowOrderPage), true, new Dictionary<string, object> { {"Order", order} }); } } }
3. 修正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:model="clr-namespace:Pension.Models" xmlns:viewmodel="clr-namespace:Pension.ViewsModels" x:DataType="viewmodel:MainViewModel" x:Class="Pension.Views.MainPage" BackgroundColor="#F2F2F2"> <VerticalStackLayout Margin="0,20,0,0" Spacing="10" FlowDirection="RightToLeft"> <Label Text="הזמנת פנסיון לכלב" FontSize="40" HorizontalOptions="Center" Margin="5"/> <Label Text="לפני שנתחיל נשמח לדעת מה התאריך בו תרצו להתארח אצלנו" HorizontalOptions="Center" FontSize="20" FontFamily="op-light"/> <Grid Padding="20" Background="#FFFFFF" Margin="54"> <Grid.Shadow> <Shadow Brush="#000" Offset="5,0" Opacity="0.26"/> </Grid.Shadow> <VerticalStackLayout Spacing="10"> <Label Text="בחירת תאריך" FontSize="30" HorizontalOptions="Center" Margin="0,0,0,15"/> <Frame x:Name="DateStart" CornerRadius="0" Padding="10,0"> <DatePicker MinimumDate="01/01/2022" MaximumDate="12/31/2025" Date="{Binding CurrentOrder.DateStart}"/> </Frame> <Frame CornerRadius="0" Padding="10,0"> <DatePicker x:Name="DateEnd" MinimumDate="01/01/2022" MaximumDate="12/31/2025" Date="{Binding CurrentOrder.DateEnd}" /> </Frame> <Frame CornerRadius="0" Padding="10,0"> <Entry x:Name="dogName" Placeholder="שם הכלב/ה" Text="{Binding CurrentOrder.DogName}"/> </Frame> <Button Text="המשך" BackgroundColor="#EEBF3E" TextColor="Black" CornerRadius="0" Command="{Binding ContinueCommand}" CommandParameter="{Binding CurrentOrder}"> <Button.Shadow> <Shadow Brush="#ccccd0" Offset="3,6" Opacity="1"/> </Button.Shadow> </Button> </VerticalStackLayout> </Grid> </VerticalStackLayout> </ContentPage>
关键修改说明
- 移除了内部
VerticalStackLayout的x:DataType="model:Order",统一使用页面的ViewModel作为绑定上下文。 - 所有输入控件的绑定路径改为
CurrentOrder.XXX,直接指向ViewModel持有的Order实例属性。 - Button的
CommandParameter直接绑定CurrentOrder,确保传递的是ViewModel中已更新的实例。
内容的提问来源于stack exchange,提问作者Matan Fadida
相关产品推荐
相关产品推荐

