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

如何实现MAUI自定义控件中Frame的点击弹窗功能?

实现MAUI自定义TimeEntryCard控件的点击弹窗功能

方案一:控件内部直接处理点击弹窗

适合固定弹窗逻辑的场景,无需父页面额外配置。

修改XAML布局

给蓝色Frame添加点击手势识别器,并绑定内部处理方法:

<?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"
             x:Class="OneCampus.Components.TimeEntryCard"
             x:Name="TimeCardEntryView">

    <VerticalStackLayout>
        <Frame BackgroundColor="Blue" 
               HorizontalOptions="Fill">
            <Frame.GestureRecognizers>
                <TapGestureRecognizer Tapped="OnCardTapped" />
            </Frame.GestureRecognizers>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Label Text="{Binding Source={x:Reference TimeCardEntryView}, Path=Day}" 
                       HorizontalOptions="Start" VerticalOptions="Center" Grid.Row="0" Grid.Column="0" />
                <VerticalStackLayout VerticalOptions="Center" Grid.Row="0" Grid.Column="1">
                    <Label Text="InTime" HorizontalOptions="Center" />
                    <Label Text="OutTime" HorizontalOptions="Center" />
                </VerticalStackLayout>
                <Label Text="TotalTime" HorizontalOptions="End" VerticalOptions="Center" Grid.Row="0" Grid.Column="2" />
            </Grid>
        </Frame>
    </VerticalStackLayout>
    
</ContentView>

修改C#后台代码

添加点击事件处理方法,实现弹窗逻辑:

namespace OneCampus.Components;

public partial class TimeEntryCard : ContentView
{
    // 必须是public static,这是MAUI定义BindableProperty的标准要求
    public static readonly BindableProperty DayProperty = BindableProperty.Create(nameof(Day), typeof(string), typeof(TimeEntryCard), string.Empty);

    public string Day
    {
        get => (string)GetValue(DayProperty);
        set => SetValue(DayProperty, value);
    }

    public TimeEntryCard()
    {
        InitializeComponent();
    }

    private async void OnCardTapped(object sender, EventArgs e)
    {
        // 弹出系统默认弹窗,可替换为自定义弹窗页面
        await Application.Current.MainPage.DisplayAlert("卡片点击", $"你点击了{Day}的考勤卡片", "确定");
    }
}

方案二:暴露可绑定命令,让父控件自定义点击逻辑

符合MVVM设计模式,允许使用控件的页面灵活定制点击行为。

修改C#后台代码

新增可绑定的命令属性,让父页面能绑定自定义逻辑:

namespace OneCampus.Components;

public partial class TimeEntryCard : ContentView
{
    public static readonly BindableProperty DayProperty = BindableProperty.Create(nameof(Day), typeof(string), typeof(TimeEntryCard), string.Empty);
    
    // 新增可绑定的点击命令属性
    public static readonly BindableProperty CardTappedCommandProperty =
        BindableProperty.Create(nameof(CardTappedCommand), typeof(ICommand), typeof(TimeEntryCard));

    public string Day
    {
        get => (string)GetValue(DayProperty);
        set => SetValue(DayProperty, value);
    }

    public ICommand CardTappedCommand
    {
        get => (ICommand)GetValue(CardTappedCommandProperty);
        set => SetValue(CardTappedCommandProperty, value);
    }

    public TimeEntryCard()
    {
        InitializeComponent();
    }
}

修改XAML布局

更新手势识别器,绑定自定义命令及参数:

<Frame BackgroundColor="Blue" 
       HorizontalOptions="Fill">
    <Frame.GestureRecognizers>
        <TapGestureRecognizer Command="{Binding Source={x:Reference TimeCardEntryView}, Path=CardTappedCommand}"
                              CommandParameter="{Binding Source={x:Reference TimeCardEntryView}, Path=Day}" />
    </Frame.GestureRecognizers>
    <!-- 原有Grid内容保持不变 -->
</Frame>

在父页面中使用

绑定ViewModel中的命令处理点击:

<!-- 父页面XAML示例 -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:components="clr-namespace:OneCampus.Components"
             x:Class="OneCampus.MainPage">

    <VerticalStackLayout>
        <components:TimeEntryCard Day="周一" CardTappedCommand="{Binding OnCardTappedCommand}" />
        <components:TimeEntryCard Day="周二" CardTappedCommand="{Binding OnCardTappedCommand}" />
    </VerticalStackLayout>
</ContentPage>

父页面ViewModel示例:

public class MainViewModel
{
    public ICommand OnCardTappedCommand => new Command<string>(async (day) =>
    {
        await Application.Current.MainPage.DisplayAlert("考勤卡片", $"选择了{day}的考勤记录", "确认");
        // 可替换为打开自定义弹窗页面、跳转页面等逻辑
    });
}

关于BindableProperty的疑问

你代码中DayProperty的public static是必须的,这是MAUI定义可绑定属性的标准规范:静态的BindableProperty实例用于注册属性,让MAUI的绑定系统能够识别和处理该属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 22:43:25