Xamarin.Forms(可为空)DatePicker:缺少确定和取消事件的解决方法

2024-02-24

我正在使用可为空的DatePicker https://developer.xamarin.com/api/type/Xamarin.Forms.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;
        }
    }
}

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

Issues:

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

已经有一个功能要求 https://xamarin.uservoice.com/forums/144858-xamarin-platform-suggestions/suggestions/16997776-xamarin-forms-datepicker-with-clear-button-to-allo,但这尚未实施。还有一些尝试 https://forums.xamarin.com/discussion/20028/datepicker-possible-to-bind-to-nullable-date-value解决这个问题,但我还没有找到一个可行的解决方案来解决我的所有问题。

我可以使用DateSelected https://developer.xamarin.com/api/event/Xamarin.Forms.DatePicker.DateSelected/事件,如果我选择今天的日期(或最后选择的日期,并且在初始化时这是今天的日期),该事件不会被触发。或者我设置NullableDate每次和取消时也会显示日期。结果,用户按下后无法清除日期cancel。我尝试尝试Unfocused事件,但我还没有找到有用的东西。也许人们可以使用ViewRenderer并交换底层的本机视图以完全控制它?但渲染器有错误的基类 https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/custom-renderer/renderers/ ...

有任何想法吗?


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

无需侦听 DateSelected 或 UnFocused 事件。

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

现在,在使用 ExtendedDatePicker 的视图中,在 .cs 文件中侦听 OnDateSelected 事件。

Example:

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

扩展 DatePicker 类:

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

希望这可以帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Xamarin.Forms(可为空)DatePicker:缺少确定和取消事件的解决方法 的相关文章

  • “字符串”是什么意思?信息'

    我刚刚在查看定义时发现了这个PlatformNotSupportedException class 什么是string message意思是 据我所知是 是缩写Nullable lt gt but Nullable lt gt 只能应用于结
  • c# - 显示小数点到小数点后 6 位 [重复]

    这个问题在这里已经有答案了 可能的重复 具有 N 个小数位的 Double ToString https stackoverflow com questions 3059759 double tostring with n number o
  • 如何通知父线程所有子线程都已终止?

    我有一个控制台应用程序正在移植到 WPF 该应用程序有 3 个工作线程 在将一些输出结果打印到屏幕上之前 这些线程都连接到主线程 我的理解是 如果我尝试在 WPF 应用程序中执行相同的操作 GUI 将被阻止并且不会响应用户 那么如何通知父线
  • C++ 和序列化:有什么方法可以进行某种内省吗?

    我读过一些例子维基百科 http en wikipedia org wiki Type introspection C 2B 2B但我正在寻找一些现实生活中的例子 如何使用内省 为什么 它有助于编写干净的代码 以及代码本身 例如 有没有办法
  • 计算复杂数组的abs()值的最快方法

    我想计算 C 或 C 中复杂数组元素的绝对值 最简单的方法是 for int i 0 i lt N i b i cabs a i 但对于大向量来说 速度会很慢 有没有办法加快速度 例如使用并行化 语言可以是 C 或 C 鉴于所有循环迭代都是
  • 我的 WPF 应用程序未触发 MainWindow_Loaded

    我目前正在关注Pluralsight C Fundamentals Part 1并在Classes and Objects视频部分指导我在 Visual Studio 中创建一个新的 WPF 应用程序并填写代码 这导致以下结果 namesp
  • 修剪 UIImage 边框

    这是我想要修剪的图像的示例 我想去掉图像周围的边框 在本例中是顶部和底部的黑条 我在Github上找到了一个库 CKImageAdditions https github com cmkilger CKImageAdditions 但是它似
  • 多维数组和指向指针的指针

    创建多维数组时char a 10 10 根据我的书 它说你必须使用类似于char a 10 将数组传递给函数 为什么必须这样指定长度 您不是只是将双指针传递给 with 并且该双指针不是已经指向分配的内存吗 那么为什么参数不能是char a
  • 如何删除实体框架6中的多对多关系

    如果将项目连接为多对多关系 则从数据库中删除项目时会出现问题 我的数据库看起来像 Project lt JobInProject gt Job ProjectID JobInProjectID JobID ProjectID JobID 主
  • ASP.NET中如何访问除wwwroot以外的位置

    我可以使用访问服务器的物理位置Server MapPath 这给了我内部的物理路径wwwroot文件夹 我想将一些数据保存到同一服务器的另一个驱动器中D 驾驶 我想我无法获取以下位置的物理位置D 驾驶使用Server MapPath因为它位
  • 为什么这个单独的定义会导致错误?

    挑战 我有这段代码无法编译 你能找出问题所在吗 有一次让我很头疼 header namespace values extern std string address extern int port cpp file std string v
  • 如何使用 ProtoGen 从 proto 文件生成结构

    我们一直在使用 protobuf net ProtoGen 从 proto 文件生成 C cs 文件 我们希望代替类来生成结构 例如 DataContract public struct Entity1 ProtoMember 1 publ
  • 将授权标头添加到 Web 参考

    我正在尝试向客户端的网络服务发出请求 我不知道客户端的底层平台 我使用 添加 Web 引用 在 Visual Studio 2010 中使用了客户端的 WSDL 并生成了我的代理类 称为 ContactService 我现在需要将如下所示的
  • #define 内存地址声明

    这个 define 语句有什么作用 它用于定义内存地址 但我不明白 uint32 t 部分 define GPxDAT uint32 t 0x6FC0 通常用于访问映射到地址空间的硬件寄存器 或者一些特定的内存地址 硬件寄存器应定义为vol
  • C++ 联合数组和变量?

    在C 中没有办法做这样的事情吗 union Scalar x y Scalar v 2 Where x v 0 and y v 1 既然您使用的是 C 而不是 C 并且它们具有相同的类型 为什么不直接将 x 设为对 v 0 的引用 将 y
  • Gridview 错误:对 Bind 的调用格式不正确

    我有以下 gridview 代码
  • 返回 ICollection 而不是 List 的真正优势是什么? [复制]

    这个问题在这里已经有答案了 我读过几篇博客文章 提到对于公共 API 我们应该始终返回 ICollection 或 IEnumerable 而不是 List 返回 ICollection 而不是 List 的真正优势是什么 Thanks 复
  • 用于 nmap 输出的 C++ xml 解析器

    我是 nmap 的新手 我在 nmap 教程中看到 https nmap org book man output html https nmap org book man output html oX 选项可用于获取 xml 格式的 nma
  • 是否可以编写一个在另一个 Windows 应用程序中选择文本时收到通知的 Windows 应用程序?

    我很好奇是否可以编写一个程序来监视我的文本选择 一种可能的用途是编写一个与编辑器 IDE 无关的代码格式化程序 应用程序 服务 P 启动并以某种方式挂接到窗口中 以便在任何窗口中选择文本时收到通知 启动其他一些应用程序 A 用户选择 A 中
  • 如何使用 Ioc Unity 注入依赖属性

    我有以下课程 public interface IServiceA string MethodA1 public interface IServiceB string MethodB1 public class ServiceA IServ

随机推荐