Xamarin.Forms视图无法识别ViewModel中email与password的问题求助
Xamarin.Forms视图无法识别ViewModel变量问题排查与解决
问题描述
在Xamarin.Forms项目中,LoginUI视图的后台代码提示email和Password变量在当前上下文不存在,同时ViewModel与View的数据绑定也存在异常。相关代码如下:
原View后台代码
using System; using Xamarin.Forms; using Xamarin.Forms.Xaml; using Papucometar.ViewModel; using Xamarin.Essentials; namespace Papucometar.View { [XamlCompilation(XamlCompilationOptions.Compile)] public partial class LoginUI : ContentPage { public LoginUI() { var vm = new LoginViewModel(); this.BindingContext = vm; vm.DisplayInvalidLoginPrompt += () => DisplayAlert("Error", "Invalid Login, try again", "OK"); InitializeComponent(); email.Completed += (object sender, EventArgs e) => { Password.Focus(); }; Password.Completed += (object sender, EventArgs e) => { vm.SubmitCommand.Execute(null); }; } } }
原ViewModel代码
using System.ComponentModel; using System.Text; using System.Windows.Input; using Xamarin.Essentials; using Xamarin.Forms; namespace Papucometar.ViewModel { public class LoginViewModel : INotifyPropertyChanged { public Action DisplayInvalidLoginPrompt; public event PropertyChangedEventHandler PropertyChanged = delegate { }; private string Email; public string email { get { return Email; } set { Email = value; PropertyChanged(this, new PropertyChangedEventArgs("Email")); } } private string password; public string Password { get { return password; } set { password = value; PropertyChanged(this, new PropertyChangedEventArgs("Password")); } } public ICommand SubmitCommand { protected set; get; } public LoginViewModel() { SubmitCommand = new Command(OnSubmit); } public void OnSubmit() { if (email != "macoratti@yahoo.com" || password != "secret") { DisplayInvalidLoginPrompt(); } } } }
原XAML代码
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Papucometar.View.LoginUI" xmlns:local="clr-namespace:Papucometar.ViewModel" x:DataType="local:LoginViewModel" BackgroundColor="#112B47"> <ContentPage.Content> <StackLayout Orientation="Vertical" Padding="30" Spacing="40"> <BoxView HeightRequest="10"/> <Image HorizontalOptions="Center" WidthRequest="300" Source="maco.jpg"/> <Frame BackgroundColor="#BF043055" HasShadow="False"> <StackLayout Orientation="Vertical" Spacing="10"> <Entry x:Name="Email" Text="{Binding Email}" Placeholder="Email" PlaceholderColor="White" HeightRequest="40" Keyboard="Email" TextColor="White"/> <Entry x:Name="Password" Text="{Binding Password}" Placeholder="Senha" PlaceholderColor="White" HeightRequest="40" IsPassword="True" TextColor="White"/> </StackLayout> </Frame> <Button Command="{Binding SubmitCommand}" Text="Login" TextColor="White" FontAttributes="Bold" FontSize="Large" HorizontalOptions="FillAndExpand" BackgroundColor="#088da5" /> </StackLayout> </ContentPage.Content> </ContentPage>
问题原因
- 控件名称大小写不匹配:View后台代码中引用的
email是小写,但XAML里Entry控件的x:Name是Email(首字母大写),C#是大小写敏感语言,因此无法找到对应控件。 - ViewModel属性命名与通知不一致:
- ViewModel的公共属性
email是小写,但PropertyChanged触发的是大写的"Email",导致数据绑定无法正确更新。 OnSubmit方法中直接使用私有字段password,而非公共属性Password,逻辑判断会读取未通过绑定更新的私有字段值。
- ViewModel的公共属性
- 绑定属性大小写不匹配:XAML中绑定的是
Email和Password,但ViewModel的对应公共属性一个是小写email,绑定逻辑因大小写不匹配失效。
解决方案
1. 修正View后台代码
将控件引用的大小写与XAML中的x:Name保持一致:
using System; using Xamarin.Forms; using Xamarin.Forms.Xaml; using Papucometar.ViewModel; using Xamarin.Essentials; namespace Papucometar.View { [XamlCompilation(XamlCompilationOptions.Compile)] public partial class LoginUI : ContentPage { public LoginUI() { var vm = new LoginViewModel(); this.BindingContext = vm; vm.DisplayInvalidLoginPrompt += () => DisplayAlert("Error", "Invalid Login, try again", "OK"); InitializeComponent(); // 修正为大写的Email,与XAML的x:Name一致 Email.Completed += (object sender, EventArgs e) => { Password.Focus(); }; Password.Completed += (object sender, EventArgs e) => { vm.SubmitCommand.Execute(null); }; } } }
2. 修正ViewModel代码
统一遵循C# PascalCase命名规范,确保属性名与通知名称一致,使用公共属性进行逻辑判断:
using System.ComponentModel; using System.Windows.Input; using Xamarin.Forms; namespace Papucometar.ViewModel { public class LoginViewModel : INotifyPropertyChanged { public Action DisplayInvalidLoginPrompt; public event PropertyChangedEventHandler PropertyChanged = delegate { }; // 私有字段用camelCase,公共属性用PascalCase private string _email; public string Email { get { return _email; } set { _email = value; // 使用nameof避免硬编码属性名 PropertyChanged(this, new PropertyChangedEventArgs(nameof(Email))); } } private string _password; public string Password { get { return _password; } set { _password = value; PropertyChanged(this, new PropertyChangedEventArgs(nameof(Password))); } } public ICommand SubmitCommand { protected set; get; } public LoginViewModel() { SubmitCommand = new Command(OnSubmit); } public void OnSubmit() { // 使用公共属性而非私有字段进行判断,同时加空引用保护 if (Email != "macoratti@yahoo.com" || Password != "secret") { DisplayInvalidLoginPrompt?.Invoke(); } } } }
3. XAML代码无需修改
XAML中的绑定路径Email和Password与修正后的ViewModel公共属性名一致,可直接使用。
内容的提问来源于stack exchange,提问作者St3fKe
相关产品推荐
相关产品推荐

