.NET MAUI .NET8绑定属性未找到问题求助
.NET MAUI .NET8 绑定警告问题
遇到以下绑定警告:
[0:] Microsoft.Maui.Controls.Xaml.Diagnostics.BindingDiagnostics: Warning: 'IsAudioEnabled' property not found on 'TTIG02_Controller.Components.ToggleSettingsItem', target property: 'TTIG02_Controller.Components.ToggleSettingsItem.IsToggled' [0:] Microsoft.Maui.Controls.Xaml.Diagnostics.BindingDiagnostics: Warning: 'IsNotificationEnabled' property not found on 'TTIG02_Controller.Components.ToggleSettingsItem', target property: 'TTIG02_Controller.Components.ToggleSettingsItem.IsToggled'
相关代码片段
SettingsPage.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="TTIG02_Controller.Views.SettingsPage" xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit" xmlns:vm="clr-namespace:TTIG02_Controller.ViewModels" xmlns:components="clr-namespace:TTIG02_Controller.Components" xmlns:local="clr-namespace:TTIG02_Controller.Views" Shell.ForegroundColor="Blue" x:DataType="vm:SettingsPageViewModel" Title="Impostazioni"> <ScrollView> <VerticalStackLayout> <!-- SEZIONE PROFILO --> <toolkit:AvatarView WidthRequest="100" HeightRequest="100" Margin="0,24,0,0" Padding="-2" ImageSource="user.png" CornerRadius="50" BorderColor="Blue" StrokeThickness="4" /> <Label Text="{Binding UserFullName}" FontSize="24" FontAttributes="Bold" HorizontalOptions="Center" Margin="0,10,0,0" /> <Label Text="{Binding UserEmail}" FontSize="16" HorizontalOptions="Center" Margin="0,4,0,0" /> <!-- SEZIONE IMPOSTAZIONI --> <components:ToggleSettingsItem Key="audio" ToggleChanged="ToggleSettingsItem_ToggleChanged" IconSource="icon_audio.svg" ItemText="Abilita suoni" IsToggled="{Binding IsAudioEnabled}" /> <components:ToggleSettingsItem Key="notification" ToggleChanged="ToggleSettingsItem_ToggleChanged" IconSource="icon_bell.svg" ItemText="Abilita notifiche" IsToggled="{Binding IsNotificationEnabled}" /> </VerticalStackLayout> </ScrollView> </ContentPage>
SettingsPage.xaml.cs
public partial class SettingsPage : ContentPage { public SettingsPage() { InitializeComponent(); BindingContext = Application.Current!.Handler.MauiContext!.Services.GetRequiredService<SettingsPageViewModel>(); } private void ToggleSettingsItem_ToggleChanged(object sender, ToggledEventArgs e) { if (sender is not ToggleSettingsItem tsi) return; if(string.IsNullOrWhiteSpace(tsi.Key)) return; if(BindingContext is not SettingsPageViewModel vm) return; Log.Verbose("SettingsPage.ToggleSettingsItem_ToggleChanged: {Key} toggled to {IsToggled}", tsi.Key, e.Value); switch(tsi.Key) { case "audio": vm.IsAudioEnabled = e.Value; break; case "notification": vm.IsNotificationEnabled = e.Value; break; default: Log.Warning("SettingsPage.ToggleSettingsItem_ToggleChanged: Unknown key {Key}", tsi.Key); break; } } }
ToggleSettingsItem.xaml
<?xml version="1.0" encoding="utf-8" ?> <ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:TTIG02_Controller.Components" x:DataType="local:ToggleSettingsItem" x:Class="TTIG02_Controller.Components.ToggleSettingsItem"> <Grid Margin="12,8,12,8"> <Grid.ColumnDefinitions> <ColumnDefinition Width="42" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="42" /> </Grid.ColumnDefinitions> <Border Grid.Column="0" BackgroundColor="#F0F0F0" StrokeShape="RoundRectangle 6" StrokeThickness="0" Padding="4" HorizontalOptions="Center" VerticalOptions="Center"> <Image Source="{Binding IconSource}" HeightRequest="32" WidthRequest="32" VerticalOptions="Center" HorizontalOptions="Center" Aspect="AspectFit" /> </Border> <Label Grid.Column="1" Text="{Binding ItemText}" FontSize="20" TextColor="Black" VerticalOptions="Center" HorizontalOptions="Start" Margin="8,0,8,0" /> <Switch x:Name="ToggleSwitch" WidthRequest="40" HeightRequest="40" Grid.Column="2" IsToggled="{Binding IsToggled, Mode=TwoWay}" HorizontalOptions="End" VerticalOptions="Center" OnColor="Blue" ThumbColor="Gray" /> </Grid> </ContentView>
ToggleSettingsItem.xaml.cs
public partial class ToggleSettingsItem : ContentView { public string Key { get => (string)GetValue(KeyProperty); set => SetValue(KeyProperty, value); } public string IconSource { get => (string)GetValue(IconSourceProperty); set => SetValue(IconSourceProperty, value); } public string ItemText { get => (string)GetValue(ItemTextProperty); set => SetValue(ItemTextProperty, value); } public bool IsToggled { get => (bool)GetValue(IsToggledProperty); set => SetValue(IsToggledProperty, value); } public static readonly BindableProperty IconSourceProperty = BindableProperty.Create( propertyName: nameof(IconSource), returnType: typeof(string), declaringType: typeof(ToggleSettingsItem), defaultValue: string.Empty, defaultBindingMode: BindingMode.OneWay ); public static readonly BindableProperty ItemTextProperty = BindableProperty.Create( propertyName: nameof(ItemText), returnType: typeof(string), declaringType: typeof(ToggleSettingsItem), defaultValue: string.Empty, defaultBindingMode: BindingMode.OneWay ); public static readonly BindableProperty IsToggledProperty = BindableProperty.Create( propertyName: nameof(IsToggled), returnType: typeof(bool), declaringType: typeof(ToggleSettingsItem), defaultValue: false, defaultBindingMode: BindingMode.TwoWay ); public static readonly BindableProperty KeyProperty = BindableProperty.Create( propertyName: nameof(Key), returnType: typeof(string), declaringType: typeof(ToggleSettingsItem), defaultValue: string.Empty, defaultBindingMode: BindingMode.OneWay ); public event EventHandler<ToggledEventArgs>? ToggleChanged; public ToggleSettingsItem() { InitializeComponent(); ToggleSwitch.Toggled += OnToggleSwitchToggled; } private void OnToggleSwitchToggled(object? sender, ToggledEventArgs e) { Log.Verbose("ToggleSettingsItem.OnToggleSwitchToggled: {ItemText} toggled to {IsToggled}", ItemText, IsToggled); ToggleChanged?.Invoke(this, e); } }
SettingsPageViewModel.cs
namespace TTIG02_Controller.ViewModels { public class SettingsPageViewModel : INotifyPropertyChanged { private bool _isAudioEnabled; public bool IsAudioEnabled { get => _isAudioEnabled; set { if (_isAudioEnabled != value) { _isAudioEnabled = value; OnPropertyChanged(nameof(IsAudioEnabled)); } } } private bool _isNotificationEnabled; public bool IsNotificationEnabled { get => _isNotificationEnabled; set { if (_isNotificationEnabled != value) { _isNotificationEnabled = value; OnPropertyChanged(nameof(IsNotificationEnabled)); } } } public event PropertyChangedEventHandler? PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }
已尝试的解决方案
- 移除
x:DataType - 设置
xmlns:local - 移除
ToggleSettingsItem中的BindingContext = this; - 使用
IsToggled="{Binding Source={x:Reference SettingsPage}, Path=BindingContext.IsNotificationEnabled}"
问题分析与解决
警告核心原因:在SettingsPage.xaml中给ToggleSettingsItem的IsToggled属性绑定时,XAML编译器错误将绑定上下文解析为ToggleSettingsItem自身,而非父页面的SettingsPageViewModel。
解决步骤
显式指定绑定源为父页面ViewModel
在SettingsPage.xaml的ToggleSettingsItem绑定中,通过RelativeSource明确指向父页面的BindingContext:<components:ToggleSettingsItem Key="audio" ToggleChanged="ToggleSettingsItem_ToggleChanged" IconSource="icon_audio.svg" ItemText="Abilita suoni" IsToggled="{Binding BindingContext.IsAudioEnabled, Source={RelativeSource AncestorType={x:Type ContentPage}}}" /> <components:ToggleSettingsItem Key="notification" ToggleChanged="ToggleSettingsItem_ToggleChanged" IconSource="icon_bell.svg" ItemText="Abilita notifiche" IsToggled="{Binding BindingContext.IsNotificationEnabled, Source={RelativeSource AncestorType={x:Type ContentPage}}}" />该方式会向上查找最近的
ContentPage类型祖先,使用其BindingContext(即SettingsPageViewModel)作为绑定源。优化代码(可选)
由于已使用双向绑定,ToggleSettingsItem_ToggleChanged事件处理可移除,绑定会自动同步ViewModel属性值,简化逻辑。
内容的提问来源于stack exchange,提问作者TimoFran
相关产品推荐
相关产品推荐

