首页 > 解决方案 > 如何捕获已在 Xamarin Forms (Android) DatePicker 上选择的默认日期?

问题描述

Currently, the DatePicker does not fire the DateSelected event when the default date is chosen. 我需要能够捕获选择日期的时间,无论它是默认日期还是任何其他日期,以便相应地更新我的数据。

标签: androidformsxamarindatepicker

解决方案


在网络上从其他人那里获得想法后,我使用了一个 Button、一个适用于 Android 和 iOS 的 DatePickerRenderer,以及 MessagingCenter。但是,我不确定这是否是一个正确的解决方案,尤其是关于 MessagingCenter 的内存泄漏 - 请随时发表评论。请参阅以下解决方案的示例代码:

Page 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>

代码隐藏页面 //共享项目

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();
            }
         }
      }
   }
}

推荐阅读