1

基本上我正在使用DatePicker来自jrgcubano的自定义渲染器实现。现在我想为 UWP 提供一个自定义渲染器。因此,我交换了 UWP 上的控件并想使用 aCalendarDatePicker来代替。

基本上,属性DateNullableDate应该是相同的(除了为NullableDate空的情况)。所以有一个同步(有时设置属性过于频繁,但这是另一回事)。我现在的经验是,它Date总是有错误的价值。大多数情况下,它具有默认值,即当前日期(或具有值 01.01.0001)。这个值好像是不能改的,因为在调试模式下改成新的值还是一样的。由于同步,它也会发生NullableDate在一次获得正确值后得到错误值的情况。要使自定义渲染器正常工作,还需要订阅该DateChanged事件。

这是我当前的实现,它显示了一个完整的工作项目:

主页.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"
             x:Class="TestExtendedDatePicker.MainPage"
             xmlns:renderer="clr-namespace:TestExtendedDatePicker;assembly=TestExtendedDatePicker"
             xmlns:sys="clr-namespace:System;assembly=mscorlib">
  <StackLayout>
    <renderer:ExtendedDatePicker x:Name="dateOfBirth"
                                NullableDate="{x:Null}"
                                MaximumDate="{x:Static sys:DateTime.Now}">
      <DatePicker.Format>dd.MM.yyyy</DatePicker.Format>
      <DatePicker.MinimumDate>
        <sys:DateTime x:FactoryMethod="Parse">
          <x:Arguments>
            <x:String>Jan 1 0001</x:String>
          </x:Arguments>
        </sys:DateTime>
      </DatePicker.MinimumDate>
    </renderer:ExtendedDatePicker>

    <Button x:Name="clearButton"
            Text="Reset"
            Clicked="OnClearButtonClicked" />
    <Button x:Name="showButton"
            Text="Show values"
            Clicked="OnShowButtonClicked" />
  </StackLayout>
</ContentPage>

MainPage.xaml.cs

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    private void OnShowButtonClicked(object sender, EventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Date: " + this.dateOfBirth.Date);
        System.Diagnostics.Debug.WriteLine("NullableDate: " + this.dateOfBirth.NullableDate);

        return;
    }

    private void OnClearButtonClicked(object sender, EventArgs e)
    {
        this.dateOfBirth.NullableDate = null;
    }
}

扩展日期选择器.cs

public class ExtendedDatePicker : DatePicker
{
    public static readonly BindableProperty NullableDateProperty =
        BindableProperty.Create("NullableDate", typeof(DateTime?), typeof(ExtendedDatePicker), null, BindingMode.TwoWay);

    public DateTime? NullableDate
    {
        get { return (DateTime?)GetValue(NullableDateProperty); }
        set
        {
            if (value != NullableDate)
            {
                SetValue(NullableDateProperty, value);
                UpdateDate();
            }
        }
    }

    protected override void OnBindingContextChanged()
    {
        base.OnBindingContextChanged();
        UpdateDate();
    }

    protected override void OnPropertyChanged(string propertyName = null)
    {
        base.OnPropertyChanged(propertyName);

        if (propertyName == DateProperty.PropertyName)
        {
            if (Date != default(DateTime))
            {
                NullableDate = Date;
            }
            else
            {
                NullableDate = null;
            }
        }

        if (propertyName == NullableDateProperty.PropertyName)
        {
            if (NullableDate.HasValue && Date != NullableDate.Value)
            {
                Date = NullableDate.Value;
            }
        }
    }

    private void UpdateDate()
    {
        if (NullableDate.HasValue)
        {
            Date = NullableDate.Value;
        }
        else
        {
            Date = (DateTime)DateProperty.DefaultValue;
            //Date = default(DateTime);
        }
    }
}

ExtendedDatePickerRenderer.cs

public class ExtendedDatePickerRenderer : ViewRenderer<Xamarin.Forms.DatePicker, Windows.UI.Xaml.Controls.CalendarDatePicker>
{
    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.DatePicker> e)
    {
        base.OnElementChanged(e);

        var view = Element as ExtendedDatePicker;

        if (e.OldElement != null || view == null)
            return;

        var calendarDatePicker = new CalendarDatePicker();
        calendarDatePicker.DateChanged += CalendarDatePicker_DateChanged;
        SetNativeControl(calendarDatePicker);

        SetNullableText(view);
    }

    private void CalendarDatePicker_DateChanged(CalendarDatePicker sender, CalendarDatePickerDateChangedEventArgs args)
    {
        var view = this.Element as ExtendedDatePicker;
        if (args.NewDate.HasValue)
        {
            DateTime newDate = args.NewDate.GetValueOrDefault().LocalDateTime.Date;
            view.NullableDate = newDate;
        }
    }

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);

        var view = (ExtendedDatePicker)Element;

        if (e.PropertyName == ExtendedDatePicker.NullableDateProperty.PropertyName)
            SetNullableText(view);
    }

    private void SetNullableText(ExtendedDatePicker view)
    {
        if (view.NullableDate == null)
            Control.Date = null;
    }
}

我必须更改与Date具有相同值的内容NullableDate?并且该值应该代表在DatePicker. 还应该有可能重置为默认值。

4

0 回答 0