You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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。

解决步骤

  1. 显式指定绑定源为父页面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)作为绑定源。

  2. 优化代码(可选)
    由于已使用双向绑定,ToggleSettingsItem_ToggleChanged事件处理可移除,绑定会自动同步ViewModel属性值,简化逻辑。

内容的提问来源于stack exchange,提问作者TimoFran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 14:23:08