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; } } } // ... 其他方法 }
关键修正点:
- 移除
IsDisplayPickerPropertyChanged的static修饰符,避免this引用错误 - 调用
ShowPopupAsync时添加await,确保正确获取异步返回值 - 泛型参数改为返回值类型(
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
相关产品推荐
相关产品推荐

