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

MAUI自定义控件中调用PopupExtensions.ShowPopupAsync时如何获取父页面

在MAUI自定义控件中获取父页面以显示CommunityToolkit Popup

问题分析

你在自定义EntryCalculator控件(继承自Frame)中调用PopupExtensions.ShowPopupAsync时,因this不是Page类型导致报错——该方法要求传入Page作为上下文参数。以下是两种可行的解决方法:


方法一:遍历视觉树获取父页面

通过遍历控件的父元素链,找到最上层的Page实例:

public partial class EntryCalculator : Frame
{
    TapGestureRecognizer _tapGestureRecognizer;

    public EntryCalculator()
    {
        InitializeComponent();
    }

    // 新增获取父页面的方法
    private Page GetParentPage()
    {
        VisualElement current = this;
        while (current.Parent != null)
        {
            current = current.Parent as VisualElement;
            if (current is Page page)
            {
                return page;
            }
        }
        return null;
    }

    private async void IsDisplayPickerPropertyChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var controls = (EntryCalculator)bindable;
        if (newValue != null && (bool)newValue)
        {
            var popup = new PickerControl();
            var parentPage = controls.GetParentPage();
            
            if (parentPage != null)
            {
                // 注意:泛型参数应为Popup返回值类型(decimal),而非Popup自身类型
                var response = await PopupExtensions.ShowPopupAsync<decimal>(parentPage, popup);
                controls.Value = response ?? controls.Value;
            }
        }
    }

    // ... 其他方法
}

关键修正点:

  1. 移除IsDisplayPickerPropertyChanged的static修饰符,避免this引用错误
  2. 调用ShowPopupAsync时添加await,确保正确获取异步返回值
  3. 泛型参数改为返回值类型(decimal),而非PickerControl

方法二:通过附加属性传入页面上下文

定义附加属性让使用控件的页面主动传入自身:

1. 创建附加属性类

public static class ParentPageAttachment
{
    public static readonly BindableProperty ParentPageProperty =
        BindableProperty.CreateAttached(
            "ParentPage", 
            typeof(Page), 
            typeof(ParentPageAttachment), 
            null);

    public static Page GetParentPage(BindableObject bindable)
    {
        return (Page)bindable.GetValue(ParentPageProperty);
    }

    public static void SetParentPage(BindableObject bindable, Page value)
    {
        bindable.SetValue(ParentPageProperty, value);
    }
}

2. 在页面XAML中绑定页面实例

<!-- 假设EntryCalculator在local命名空间下 -->
<local:EntryCalculator 
    local:ParentPageAttachment.ParentPage="{Binding Source={RelativeSource Mode=Self}}" />

3. 在控件中获取页面并显示Popup

private async void IsDisplayPickerPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
    var controls = (EntryCalculator)bindable;
    if (newValue != null && (bool)newValue)
    {
        var popup = new PickerControl();
        var parentPage = ParentPageAttachment.GetParentPage(controls);
        
        if (parentPage != null)
        {
            var response = await PopupExtensions.ShowPopupAsync<decimal>(parentPage, popup);
            controls.Value = response ?? controls.Value;
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 22:15:33