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

如何在MAUI中创建带事件处理器的自定义控件?解决编译错误

解决MAUI自定义控件ClickAction绑定编译错误

我在MAUI中创建了一个包含两个按钮的自定义控件,希望开发者使用时能给按钮绑定点击处理逻辑,但在页面中引用控件并指定ClickAction时出现编译错误。


自定义控件C#代码

public partial class BottomButtons : Grid
{
    public BottomButtons()
    {
        InitializeComponent();
    }

    public BindableProperty LeftButtonTextProperty = BindableProperty.Create(propertyName: nameof(LeftButtonText),
                                                                    returnType: typeof(String),
                                                                    defaultValue: "Cancel",
                                                                    defaultBindingMode: BindingMode.OneWay,
                                                                    declaringType: typeof(BottomButtons)
                                                                    );
    public String LeftButtonText
    {
        get => (String)GetValue(LeftButtonTextProperty);
        set { SetValue(LeftButtonTextProperty, value); }
    }


    public BindableProperty RightButtonTextProperty = BindableProperty.Create(propertyName: nameof(RightButtonText),
                                                                    returnType: typeof(String),
                                                                    defaultValue: "Save",
                                                                    defaultBindingMode: BindingMode.OneWay,
                                                                    declaringType: typeof(BottomButtons)
                                                                    );

    public String RightButtonText
    {
        get => (String)GetValue(RightButtonTextProperty);
        set { SetValue(RightButtonTextProperty, value); }
    }

    public BindableProperty ClickActionProperty = BindableProperty.Create(propertyName: nameof(ClickAction),
                                                                    returnType: typeof(EventHandler),
                                                                    defaultValue: null,
                                                                    defaultBindingMode: BindingMode.OneWay,
                                                                    declaringType: typeof(BottomButtons)
                                                                    );
    public EventHandler ClickAction
    {
        get => (EventHandler)GetValue(ClickActionProperty);
        set {SetValue(ClickActionProperty, value); }
    }

}

自定义控件XAML代码

<Grid xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Resources.Controls.BottomButtons"
             ColumnDefinitions="*,*" Padding="10" ColumnSpacing="20"
             x:Name="this">

    <Button Text="{Binding Source={x:Reference this},Path=RightButtonText}" Grid.Column="1" HorizontalOptions="Fill"></Button>
    <Button Text="{Binding Source={x:Reference this},Path=LeftButtonText}" Grid.Column="0" HorizontalOptions="Fill"></Button>

</Grid>

页面引用代码

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="Pages.SeancesSelector"
               xmlns:viewmodel="clr-namespace:ViewModels" xmlns:VerticalStackLayout="clr-namespace:Resources.Controls">

        <!-- Something... -->
        <BottomButtons ClickAction="MyEventHandler"/>  <!-- Custom control inserted here -->
        
</ContentPage>

页面C#代码

public partial class SeancesSelector : ContentPage //Popup
{

    public SeancesSelector()
    {
        InitializeComponent();          
    }       

    public void MyEventHandler(Object Sender, EventArgs E)
    {

    }
}

编译错误信息

No property, BindableProperty, or event found for "ClickAction", or mismatching type between value and property.


问题分析与解决方法

你的猜测是正确的:XAML中ClickAction="MyEventHandler"的写法是事件绑定语法,但你定义的ClickAction是一个BindableProperty属性,编译器无法匹配,因此报错。此外还有两个细节问题:页面XAML的命名空间别名错误,以及自定义控件的按钮未关联点击逻辑。

推荐方案:改为自定义事件(符合MAUI控件设计规范)

将ClickAction改为事件,适配XAML的事件绑定语法,同时修正其他细节:

  1. 修改自定义控件C#代码
    把BindableProperty改为标准的static readonly格式,同时添加两个按钮的自定义事件:

    public partial class BottomButtons : Grid
    {
        public BottomButtons()
        {
            InitializeComponent();
            // 绑定按钮点击到自定义事件
            LeftButton.Clicked += (s, e) => LeftButtonClicked?.Invoke(this, e);
            RightButton.Clicked += (s, e) => RightButtonClicked?.Invoke(this, e);
        }
    
        // 左按钮点击事件
        public event EventHandler LeftButtonClicked;
        // 右按钮点击事件
        public event EventHandler RightButtonClicked;
    
        // 文本属性(修正为标准写法)
        public static readonly BindableProperty LeftButtonTextProperty = BindableProperty.Create(
            nameof(LeftButtonText),
            typeof(string),
            typeof(BottomButtons),
            "Cancel",
            BindingMode.OneWay);
        public string LeftButtonText
        {
            get => (string)GetValue(LeftButtonTextProperty);
            set => SetValue(LeftButtonTextProperty, value);
        }
    
        public static readonly BindableProperty RightButtonTextProperty = BindableProperty.Create(
            nameof(RightButtonText),
            typeof(string),
            typeof(BottomButtons),
            "Save",
            BindingMode.OneWay);
        public string RightButtonText
        {
            get => (string)GetValue(RightButtonTextProperty);
            set => SetValue(RightButtonTextProperty, value);
        }
    }
    
  2. 修改自定义控件XAML
    给按钮命名,方便后台绑定事件:

    <Grid xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
          x:Class="Resources.Controls.BottomButtons"
          ColumnDefinitions="*,*" Padding="10" ColumnSpacing="20">
    
        <Button x:Name="LeftButton" Text="{Binding LeftButtonText, Source={RelativeSource Self}}" Grid.Column="0" HorizontalOptions="Fill"/>
        <Button x:Name="RightButton" Text="{Binding RightButtonText, Source={RelativeSource Self}}" Grid.Column="1" HorizontalOptions="Fill"/>
    
    </Grid>
    
  3. 修改页面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="Pages.SeancesSelector"
                 xmlns:viewmodel="clr-namespace:ViewModels" 
                 xmlns:controls="clr-namespace:Resources.Controls">
    
        <!-- Something... -->
        <controls:BottomButtons LeftButtonClicked="LeftButton_Clicked" RightButtonClicked="RightButton_Clicked"/>
        
    </ContentPage>
    
  4. 页面C#添加事件处理方法

    public partial class SeancesSelector : ContentPage
    {
        public SeancesSelector()
        {
            InitializeComponent();          
        }       
    
        private void LeftButton_Clicked(object sender, EventArgs e)
        {
            // 左按钮点击逻辑
        }
    
        private void RightButton_Clicked(object sender, EventArgs e)
        {
            // 右按钮点击逻辑
        }
    }
    

备选方案:坚持使用BindableProperty(不推荐)

如果一定要用属性传递EventHandler,需要用绑定语法而非事件写法:

  1. 自定义控件中给按钮绑定属性对应的逻辑;
  2. 页面XAML中用{Binding}语法传递EventHandler属性,同时确保页面的方法是EventHandler类型的属性而非普通方法。这种方式繁琐且不符合MAUI常规用法,不推荐使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 12:45:51