【问题标题】:Xamarin.Forms (Nullable) DatePicker: Workaround for missing OK and cancel eventsXamarin.Forms (Nullable) DatePicker:缺少 OK 和取消事件的解决方法
【发布时间】:2017-07-31 15:33:02
【问题描述】:

我正在使用可以为空的DatePicker,它是通过从DatePicker 继承并使用自定义渲染器来实现的。

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

    public static readonly BindableProperty PlaceholderProperty =
        BindableProperty.Create(
            "Placeholder", 
            typeof(string), 
            typeof(ExtendedDatePicker), 
            string.Empty, 
            BindingMode.OneWay);

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

    public string Placeholder
    {
        get { return (string)GetValue(PlaceholderProperty); }
        set { SetValue(PlaceholderProperty, value); }
    }

    public ExtendedDatePicker()
    {
        //this.Unfocused += ExtendedDatePicker_Unfocused;
        //this.DateSelected += ExtendedDatePicker_DateSelected;
    }

    //private void ExtendedDatePicker_DateSelected(object sender, DateChangedEventArgs e)
    //{
    //    NullableDate = Date;
    //}

    //private void ExtendedDatePicker_Unfocused(object sender, FocusEventArgs e)
    //{
    //    if (Device.RuntimePlatform == Device.Android && !e.IsFocused)
    //    {
    //        NullableDate = Date;
    //    }
    //}

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

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

        if (propertyName == IsFocusedProperty.PropertyName)
        {
            if (IsFocused)
            {
                if (!NullableDate.HasValue)
                {
                    Date = (DateTime)DateProperty.DefaultValue;
                }
            }
            else
            {
                OnPropertyChanged(DateProperty.PropertyName);
            }
        }

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

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

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

我不在这里提供自定义渲染器,因为它们大多是 setter。我目前的方法有效,但是必须通过一个额外的按钮来清除所选日期,并且按下“取消”仍然会在日期选择器中设置日期。现在我想改善这种行为,并且正在寻找更好的解决方案。

问题:

  • 用户应该能够从日期选择器中选择任何日期(包括今天)
  • 能够清除当前选择的日期
  • 取消的行为应该类似于取消(并清除日期)
  • 适用于所有平台(iOS、Droid、UWP)

已经有一个feature request,但这还没有实现。还有some tries 可以解决这个问题,但是我还没有找到可以解决我所有问题的有效解决方案。

我可以使用DateSelected 事件,如果我选择今天的日期(或者最后选择的日期是准确的并且在初始化时这是今天的日期),它不会被触发。或者我每次都设置NullableDate,取消时也会显示日期。结果,如果用户按cancel,则无法清除日期。我尝试尝试Unfocused 事件,但我没有找到有用的东西。也许可以使用ViewRenderer 并交换底层的原生视图以完全控制它?但是渲染器有wrong base classes ...

有什么想法吗?

【问题讨论】:

  • 创建自定义控件的想法怎么样?您可以提供额外的按钮和覆盖属性需要不同的行为。因此,不要将 DatePicker 子类化,而是将其添加为控件的成员
  • @YuriS:是的,自定义控件是一种方式。但是对于平台细节,您仍然需要自定义渲染器。

标签: c# xamarin datepicker xamarin.forms nullable


【解决方案1】:

我已经找到了解决方案。为此付出了很多努力。

无需监听 DateSelected 或 UnFocused 事件。

基本上我们在 ExtendedDatePicker 中创建一个事件,然后在单击完成/取消时调用此事件,可能是 UpdateDate 方法或基于您设置日期的流程。

现在查看使用 ExtendedDatePicker 的位置,在 .cs 文件中侦听 OnDateSelected 事件。

例子:

.xaml 文件:

<xyz:BorderlessDatePicker x:Name="drawCalender" Format="dd-MMM-yyyy" />

.xaml.cs 文件:

drawCalender.OnDateSelected += (object sender, DateChangedEventArgs e) =>
                {
                    ExtendedDatePicker calendarPicker = (ExtendedDatePicker)sender;
                    if (calendarPicker.NullableDate != null)
                    {
                        CalendarText = (DateTime)calendarPicker.NullableDate;
                    }
                    else
                    {
                        CalendarText = null;
                    }
                };

ExtendedDatePicker 类:

public class ExtendedDatePicker : DatePicker
{
    public delegate void DateSelectedHandler(object sender, DateChangedEventArgs e);
    public event DateSelectedHandler OnDateSelected;

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


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

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

        if (propertyName == IsFocusedProperty.PropertyName)
        {
            if (IsFocused)
            {
                if (!NullableDate.HasValue)
                {
                    Date = (DateTime)DateProperty.DefaultValue;
                }
            }
            else
            {
                OnPropertyChanged(DateProperty.PropertyName);
            }
        }

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

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

    private void UpdateDate()
    {
        if (NullableDate.HasValue)
        {
            Date = NullableDate.Value;
        }
        else
        {
            Date = (DateTime)DateProperty.DefaultValue;
        }
        OnDateSelected(this, null);
    }
}

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,我以这种简单的方式解决了:我添加了一个转换器,如果日期为空,则返回 color.transparent,如果日期不为空,则返回 color.black;然后我在日期选择器的TextColor 上在 XAML 中使用了这个转换器。结果是,如果日期为空,日期选择器似乎为空;但是,如果你选择一个日期,颜色就会变成黑色。

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-19
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 2019-12-05
    • 2016-10-19
    • 2011-05-07
    相关资源
    最近更新 更多