Получив идеи от других в Интернете, я использовал Button, DatePickerRenderer для Android и iOS, а также MessagingCenter. Однако я не уверен, что это правильное решение, особенно в отношении утечек памяти в MessagingCenter. Пожалуйста, не стесняйтесь комментировать. См. Пример кода для решения ниже:
Страница XAML // Общий проект
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="MyDatePickerApp.PickDatePage">
<ContentPage.Content>
<StackLayout VerticalOptions="Center" Margin="20">
<Button x:Name="StartDateBtn"
Text="Start Date"
BackgroundColor="Silver"
TextColor="White"
Clicked="StartDateBtn_Clicked"
VerticalOptions="Center"
HorizontalOptions="FillAndExpand"/>
<DatePicker x:Name="StartDatePicker"
IsEnabled="True"
IsVisible="False"/>
</StackLayout>
</ContentPage.Content>
Код за страницей // SharedПроект
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace MyDatePickerApp
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class PickDatePage : ContentPage
{
public PickDatePage()
{
InitializeComponent();
MessagingCenter.Subscribe<DatePicker>(this, "OK", (sender) => {
UpdateDate(sender); });
MessagingCenter.Subscribe<DatePicker>(this, "Cancelled", (sender) => {
CancelDate(sender); });
MessagingCenter.Subscribe<DatePicker>(this, "Cleared", (sender) => {
ClearDate(sender); });
}
private void StartDateBtn_Clicked(object sender, EventArgs e)
{
StartDateBtn.InputTransparent = true;
StartDatePicker.MinimumDate = DateTime.Now.AddDays(-90);
StartDatePicker.MaximumDate = DateTime.Now.AddYears(3);
StartDatePicker.Format = "MM/dd/yyyy";
if(StartDateBtn.Text != "Start Date")
{
var tmpDateString = StartDateBtn.Text;
var tmpDateStringSub = tmpDateString.Substring(12);
StartDatePicker.Date = Convert.ToDateTime(tmpDateStringSub);
}
else
{
StartDatePicker.Date = DateTime.Now;
}
StartDatePicker.Focus();
}
private void UpdateDate(DatePicker sender)
{
var myDP = sender;
var rawDate = StartDatePicker.Date;
StartDateBtn.Text = "Start Date: " + rawDate.ToString("MM/dd/yyyy");
StartDatePicker.Unfocus();
StartDateBtn.InputTransparent = false;
}
private void ClearDate(DatePicker sender)
{
var myDP = sender;
StartDateBtn.Text = "Start Date";
StartDatePicker.Unfocus();
StartDateBtn.InputTransparent = false;
}
private void CancelDate(DatePicker sender)
{
var myDP = sender;
StartDatePicker.Unfocus();
StartDateBtn.InputTransparent = false;
}
protected override void OnDisappearing()
{
MessagingCenter.Unsubscribe<DatePicker>(this, "OK");
MessagingCenter.Unsubscribe<DatePicker>(this, "Cancelled");
MessagingCenter.Unsubscribe<DatePicker>(this, "Cleared");
base.OnDisappearing();
}
}
}
Android DatePickerRenderer // Проект Android
using Android.App;
using Android.Content;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using MyDatePickerApp.Droid;
[assembly:ExportRenderer(typeof(Xamarin.Forms.DatePicker),
typeof(ADatePickerRenderer))]
namespace MyDatePickerApp.Droid
{
public class ADatePickerRenderer : DatePickerRenderer
{
public ADatePickerRenderer(Context context) : base(context)
{
}
protected override DatePickerDialog CreateDatePickerDialog(int year, int month, int day)
{
Xamarin.Forms.DatePicker view = (Xamarin.Forms.DatePicker)Element;
var dialog = new DatePickerDialog(Context, (o, e) =>{}, year, month, day);
dialog.SetButton("OK", (sender, e) => { var nativePickerDialog = (Android.App.DatePickerDialog)sender; view.Date = nativePickerDialog.DatePicker.DateTime; MessagingCenter.Send(view, "OK"); });
dialog.SetButton2("Cancel", (sender, e) => { var nativePickerDialog =(Android.App.DatePickerDialog)sender; view.Date =nativePickerDialog.DatePicker.DateTime; MessagingCenter.Send(view, "Cancelled"); });
dialog.SetButton3("Clear", (sender, e) => { var nativePickerDialog =(Android.App.DatePickerDialog)sender; view.Date = nativePickerDialog.DatePicker.DateTime; MessagingCenter.Send(view, "Cleared"); });
return dialog;
//return base.CreateDatePickerDialog(year, month, day);
}
}
}
iOS DatePickerRenderer // Проект iOS
using System.Collections.Generic;
using System.Linq;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using MyDatePickerApp.iOS;
[assembly: ExportRenderer(typeof(Xamarin.Forms.DatePicker), typeof(iosDatePickerRenderer))]
namespace MyDatePickerApp.iOS
{
public class iosDatePickerRenderer : DatePickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
{
base.OnElementChanged(e);
if (e.NewElement != null && Control != null)
{
var view = Element;
var tbar = Control.InputAccessoryView as UIToolbar;
var origItems = tbar.Items;
var newItems = new List<UIBarButtonItem>();
if (origItems.Count() < 3)
{
var clearItem = new UIBarButtonItem("Clear", UIBarButtonItemStyle.Plain, (sender, ev) =>{ MessagingCenter.Send(view, "Cleared"); });
newItems.Add(clearItem);
var flexspace = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace);
newItems.Add(flexspace);
var cancelItem = new UIBarButtonItem("Cancel", UIBarButtonItemStyle.Plain, (sender, ev) =>{ MessagingCenter.Send(view, "Cancelled"); });
newItems.Add(cancelItem);
var OKItem = new UIBarButtonItem("Done", UIBarButtonItemStyle.Plain, (sender, ev) => { MessagingCenter.Send(view, "OK"); });
newItems.Add(OKItem);
tbar.Items = newItems.ToArray();
}
}
}
}
}