Xamarin Forms MVVM绑定报错:ViewModel中找不到Model属性N2
Hey there, let's break down why your binding is throwing that 'N2' property not found error and get it working correctly. Here are the key issues and fixes:
1. You're Binding to a Field, Not a Property
Xamarin.Forms' binding system only works with public properties, not fields. In your MainPageViewModel, calculator is a field:
public Calculator calculator; // This is a field, binding can't access it
Change it to a public property (follow C# naming conventions with a capitalized name):
// Now binding can access this property public Calculator Calculator { get; set; }
Then update your XAML binding paths to match the capitalized property name:
<Entry x:Name="n1" Text="{Binding Calculator.N1}" ></Entry> <Entry x:Name="n2" Text="{Binding Calculator.N2}" ></Entry>
2. Your Calculator Properties Aren't Notifying of Changes
Even though you implemented INotifyPropertyChanged in your Calculator class, none of your property setters are calling OnPropertyChanged(). This means when the UI updates values, the ViewModel won't pick up changes, and vice versa.
Update each property in Calculator to trigger the property changed event:
private decimal n1; public decimal N1 { get { return n1; } set { if (n1 != value) { n1 = value; OnPropertyChanged(); // Notify UI of value change } } } private decimal n2; public decimal N2 { get { return n2; } set { if (n2 != value) { n2 = value; OnPropertyChanged(); } } } private decimal division; public decimal Division { get { return division; } set { if (division != value) { division = value; OnPropertyChanged(); } } }
3. Handle String-to-Decimal Conversion (Critical for Entry Controls)
The Entry control's Text property is a string, but your Calculator properties are decimal. Direct binding here can cause parsing errors (like when the user enters an empty string or non-numeric text).
Create a value converter to safely handle this conversion:
public class StringToDecimalConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return value is decimal dec ? dec.ToString(culture) : string.Empty; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { if (value is string input && decimal.TryParse(input, out decimal result)) { return result; } return 0m; // Fallback to 0 if parsing fails } }
Add the converter to your page's resources:
<ContentPage.Resources> <local:StringToDecimalConverter x:Key="StringToDecimalConverter" /> </ContentPage.Resources>
Then update your Entry bindings to use the converter:
<Entry x:Name="n1" Text="{Binding Calculator.N1, Converter={StaticResource StringToDecimalConverter}}" ></Entry> <Entry x:Name="n2" Text="{Binding Calculator.N2, Converter={StaticResource StringToDecimalConverter}}" ></Entry>
4. Add Safety for Division
In your DoOperations method, add a check to avoid division by zero (a common runtime error):
private void DoOperations() { if (Calculator.N2 != 0) { Calculator.Division = Calculator.N1 / Calculator.N2; } else { // Handle division by zero (e.g., set a fallback value or notify the user) Calculator.Division = 0; // Optional: Show an alert to the user // Application.Current.MainPage.DisplayAlert("Error", "Cannot divide by zero!", "OK"); } }
After applying all these fixes, your bindings should work correctly, and the N2 property not found error should disappear.
内容的提问来源于stack exchange,提问作者Jaime Santos

