使用不同的本机控件时,未在自定义渲染器中设置的值

时间:2016-12-06 08:03:15

标签: c# xaml uwp xamarin.forms custom-renderer

基本上我正在使用来自jrgcubanoDatePicker的自定义渲染器实现。现在我想为UWP提供自定义渲染器。因此,我在UWP上交换控件,并希望改为使用CalendarDatePicker

基本上,属性DateNullableDate应该相同(除了NullableDate为空的情况除外)。所以有一个同步(有时会经常设置属性,但这是另一个故事)。我现在经历的是,Date总是错误的价值。大多数情况下,它具有默认值,即当前日期(或者值为01.01.0001)。该值似乎无法更改,因为在调试模式下,它在更改为新值后仍具有相同的值。由于同步,NullableDate在一次具有正确值后得到错误的值也会发生。要使自定义渲染器正常工作,还必须订阅DateChanged事件。

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

MainPage.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;
    }
}

ExtendedDatePicker.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;
    }
}

我需要更改DateNullableDate具有相同价值的内容吗?该值应代表DatePicker中选择的值。还应该可以重置为默认值。

0 个答案:

没有答案