.NET MAUI 9中CommandParameter设置属性后值不保留问题排查
.NET MAUI 9中Entry占位文本不更新的问题分析与解决
问题描述
在.NET MAUI 9中编写示例,通过按钮点击时的CommandParameter值设置ViewModel的属性,该属性作为Entry控件Placeholder的绑定源。预期点击“Set PropertyOne”按钮后,Entry的占位文本显示为“Text from Property”。调试时确认EntryPlaceholderText属性被正确设置,但命令执行后该属性值看似被重置,Entry无占位文本显示。
视图代码
<?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="MauiBindingExample.MainPage" xmlns:local="clr-namespace:MauiBindingExample.ViewModels"> <ScrollView> <VerticalStackLayout Padding="30,0" Spacing="25"> <Image Source="dotnet_bot.png" HeightRequest="185" Aspect="AspectFit" SemanticProperties.Description="dot net bot in a hovercraft number nine" /> <Button BindingContext="{local:ExampleViewModel}" x:DataType="local:ExampleViewModel" Text="Set PropertyOne" Command="{Binding SetPropertyOneCommand}" CommandParameter="Text from Property"/> <Entry BindingContext="{local:ExampleViewModel}" x:DataType="local:ExampleViewModel" PlaceholderColor="AliceBlue" Placeholder="{Binding EntryPlaceholderText}"/> </VerticalStackLayout> </ScrollView> </ContentPage>
ViewModel代码
using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows.Input; namespace MauiBindingExample.ViewModels { public class ExampleViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private string entryPlaceholderText; public string EntryPlaceholderText { get => entryPlaceholderText; set { entryPlaceholderText = value; OnPropertyChanged(); } } public ICommand SetPropertyOneCommand { get; set; } public ExampleViewModel() { SetPropertyOneCommand = new Command<string>( (string arg) => { EntryPlaceholderText = arg; }); } public void OnPropertyChanged([CallerMemberName] string propertyName="") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }
问题根源
按钮和Entry控件各自通过BindingContext="{local:ExampleViewModel}"创建了独立的ExampleViewModel实例:
- 按钮点击时修改的是自身绑定的ViewModel实例中的
EntryPlaceholderText属性 - Entry控件绑定的是另一个全新的ViewModel实例,该实例的
EntryPlaceholderText始终为初始值null
所以调试时看到的属性被正确设置是按钮对应的ViewModel实例,而Entry对应的实例属性并未被修改,导致占位文本无法显示。
解决方案
方案1:将ViewModel设置为页面的BindingContext(推荐)
在页面级别设置BindingContext,让所有子控件继承同一个ViewModel实例,去掉按钮和Entry的BindingContext设置:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MauiBindingExample.MainPage" xmlns:local="clr-namespace:MauiBindingExample.ViewModels" BindingContext="{local:ExampleViewModel}"> <ScrollView> <VerticalStackLayout Padding="30,0" Spacing="25"> <Image Source="dotnet_bot.png" HeightRequest="185" Aspect="AspectFit" SemanticProperties.Description="dot net bot in a hovercraft number nine" /> <Button x:DataType="local:ExampleViewModel" Text="Set PropertyOne" Command="{Binding SetPropertyOneCommand}" CommandParameter="Text from Property"/> <Entry x:DataType="local:ExampleViewModel" PlaceholderColor="AliceBlue" Placeholder="{Binding EntryPlaceholderText}"/> </VerticalStackLayout> </ScrollView> </ContentPage>
方案2:使用静态资源共享同一个ViewModel实例
在页面的资源字典中定义ViewModel实例,让按钮和Entry引用同一个资源:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MauiBindingExample.MainPage" xmlns:local="clr-namespace:MauiBindingExample.ViewModels"> <ContentPage.Resources> <local:ExampleViewModel x:Key="SharedViewModel"/> </ContentPage.Resources> <ScrollView> <VerticalStackLayout Padding="30,0" Spacing="25"> <Image Source="dotnet_bot.png" HeightRequest="185" Aspect="AspectFit" SemanticProperties.Description="dot net bot in a hovercraft number nine" /> <Button BindingContext="{StaticResource SharedViewModel}" x:DataType="local:ExampleViewModel" Text="Set PropertyOne" Command="{Binding SetPropertyOneCommand}" CommandParameter="Text from Property"/> <Entry BindingContext="{StaticResource SharedViewModel}" x:DataType="local:ExampleViewModel" PlaceholderColor="AliceBlue" Placeholder="{Binding EntryPlaceholderText}"/> </VerticalStackLayout> </ScrollView> </ContentPage>
内容的提问来源于stack exchange,提问作者rochitsen
相关产品推荐
相关产品推荐

