如何在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的事件绑定语法,同时修正其他细节:
修改自定义控件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); } }修改自定义控件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>修改页面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>页面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,需要用绑定语法而非事件写法:
- 自定义控件中给按钮绑定属性对应的逻辑;
- 页面XAML中用
{Binding}语法传递EventHandler属性,同时确保页面的方法是EventHandler类型的属性而非普通方法。这种方式繁琐且不符合MAUI常规用法,不推荐使用。
内容的提问来源于stack exchange,提问作者Thomas Carlton
相关产品推荐
相关产品推荐

