.NET MAUI iOS:如何将DatePicker的日期视图独立为自定义控件
iOS平台.NET MAUI自定义无Entry日期选择视图实现方案
需求说明
iOS平台的.NET MAUI DatePicker默认包含Entry输入框,获取焦点后弹出日期选择视图,需点击Done按钮才会同步日期到Entry。现需实现一个仅渲染滚轮式日期选择视图的自定义控件(继承自View),无需Entry和Done按钮,直接在XAML中插入即可显示选择界面。
过往Xamarin实现思路回顾
在Xamarin中,曾计划通过继承DatePickerRenderer,尝试提取DatePicker的原生日期选择视图(疑似InputView/InputAccessoryView),再通过SetNativeControl()将其挂载到自定义View上,伪代码如下:
public class CustomDatePickerRenderer : DatePickerRenderer { protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); // 尝试获取DatePicker的原生日期选择视图 // Control... // 通过SetNativeControl将选择视图设置为自定义控件的原生控件 // SetNativeControl(); } }
MAUI当前卡点
迁移到MAUI后,已知通过Handler访问原生控件,但不清楚:
- 如何获取DatePicker的日期选择视图
- 如何将该视图挂载到自定义
DateViewer(继承自View)上
当前尝试的MAUI伪代码:
Microsoft.Maui.Handlers.DatePickerHandler.Mapper.AppendToMapping("DateViewerCustomization", (handler, view) => { if (view is DateViewer) { #if IOS // 未知如何获取iOS平台DatePicker的日期选择视图 handler.PlatformView... #endif } });
自定义DateViewer伪代码:
public partial class DateViewer : View { public DateViewer() { InitializeComponent(); } }
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" xmlns:controls="clr-namespace:Test.Controls" x:Class="Test" Title="Test"> <ContentPage.Content> <VerticalStackLayout> <controls:DateViewer /> </VerticalStackLayout> </ContentPage.Content> </ContentPage>
解决方案建议(MAUI iOS专属)
核心思路
放弃从MAUI DatePicker中提取视图的方式,直接在自定义Handler中创建iOS原生UIDatePicker作为平台视图,绑定自定义控件的日期属性,实现完全独立的日期选择视图。
完整代码实现
1. 共享项目:自定义DateViewer控件
using Microsoft.Maui.Controls; namespace Test.Controls; public class DateViewer : View { // 定义可绑定的SelectedDate属性 public static readonly BindableProperty SelectedDateProperty = BindableProperty.Create(nameof(SelectedDate), typeof(DateTime?), typeof(DateViewer), default(DateTime?)); public DateTime? SelectedDate { get => (DateTime?)GetValue(SelectedDateProperty); set => SetValue(SelectedDateProperty, value); } }
2. iOS项目:创建DateViewer专属Handler
using Foundation; using Microsoft.Maui.Handlers; using Test.Controls; using UIKit; namespace Test.Platforms.iOS; public partial class DateViewerHandler : ViewHandler<DateViewer, UIDatePicker> { // 创建原生UIDatePicker作为平台视图 protected override UIDatePicker CreatePlatformView() { var datePicker = new UIDatePicker { Mode = UIDatePickerMode.Date, PreferredDatePickerStyle = UIDatePickerStyle.Wheels, // 使用滚轮式样式 TranslatesAutoresizingMaskIntoConstraints = false }; // 监听日期变化,同步到自定义控件属性 datePicker.ValueChanged += OnDateChanged; return datePicker; } private void OnDateChanged(object sender, EventArgs e) { if (sender is UIDatePicker picker && VirtualView != null) { VirtualView.SelectedDate = picker.Date.ToDateTime(); } } // 初始化控件日期 protected override void ConnectHandler(UIDatePicker platformView) { base.ConnectHandler(platformView); if (VirtualView.SelectedDate.HasValue) { platformView.Date = VirtualView.SelectedDate.Value.ToNSDate(); } } // 清理事件监听 protected override void DisconnectHandler(UIDatePicker platformView) { platformView.ValueChanged -= OnDateChanged; base.DisconnectHandler(platformView); } // 处理SelectedDate属性的绑定更新 public static void MapSelectedDate(DateViewerHandler handler, DateViewer view) { if (handler.PlatformView != null && view.SelectedDate.HasValue) { handler.PlatformView.Date = view.SelectedDate.Value.ToNSDate(); } } }
3. iOS项目:注册Handler
在Program.cs中添加Handler注册:
using Microsoft.Maui; using Microsoft.Maui.Hosting; using Test.Controls; using Test.Platforms.iOS; namespace Test; public static class MauiProgram { public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); }); // 注册DateViewer的iOS Handler builder.ConfigureMauiHandlers(handlers => { #if IOS handlers.AddHandler<DateViewer, DateViewerHandler>(); #endif }); return builder.Build(); } }
4. 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" xmlns:controls="clr-namespace:Test.Controls" x:Class="Test.MainPage" Title="Test"> <ContentPage.Content> <VerticalStackLayout Padding="20" Spacing="10"> <controls:DateViewer SelectedDate="{Binding SelectedDate}" HeightRequest="200"/> <!-- 指定高度适配滚轮视图 --> <Label Text="{Binding SelectedDate, StringFormat='选中日期: {0:yyyy-MM-dd}'}"/> </VerticalStackLayout> </ContentPage.Content> </ContentPage>
关键说明
- 直接使用iOS原生
UIDatePicker,避免依赖MAUI DatePicker的Entry逻辑,实现更简洁可控。 - MAUI中Handler的
CreatePlatformView方法替代了Xamarin的SetNativeControl,负责创建并返回自定义控件的原生视图。 - 可通过调整
UIDatePicker.PreferredDatePickerStyle修改显示样式,Wheels即为需求中的滚动选择视图。
内容的提问来源于stack exchange,提问作者MonoMatrix
相关产品推荐
相关产品推荐

