From 939860578200308d27e488cb3ec799814fe578c8 Mon Sep 17 00:00:00 2001 From: rabbitism Date: Thu, 20 Jun 2024 18:38:10 +0800 Subject: [PATCH] feat: improve range pick behavior. --- demo/Ursa.Demo/Pages/DatePickerDemo.axaml.cs | 4 +- .../CalendarDayButtonEventArgs.cs | 4 +- .../Controls/DateTimePicker/CalendarView.cs | 13 ++- .../DateTimePicker/DateRangePicker.cs | 79 +++++++++++++++---- 4 files changed, 77 insertions(+), 23 deletions(-) diff --git a/demo/Ursa.Demo/Pages/DatePickerDemo.axaml.cs b/demo/Ursa.Demo/Pages/DatePickerDemo.axaml.cs index 7517a50..e38d30d 100644 --- a/demo/Ursa.Demo/Pages/DatePickerDemo.axaml.cs +++ b/demo/Ursa.Demo/Pages/DatePickerDemo.axaml.cs @@ -15,11 +15,11 @@ public partial class DatePickerDemo : UserControl private void CalendarView_OnOnDateSelected(object? sender, CalendarDayButtonEventArgs e) { - Debug.WriteLine("Pressed: "+ e.Date.ToLongDateString()); + Debug.WriteLine("Pressed: "+ e.Date?.ToLongDateString()); } private void CalendarView_OnOnDatePreviewed(object? sender, CalendarDayButtonEventArgs e) { - Debug.WriteLine("Hovered: "+e.Date.ToLongDateString()); + Debug.WriteLine("Hovered: "+e.Date?.ToLongDateString()); } } \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/CalendarDayButtonEventArgs.cs b/src/Ursa/Controls/DateTimePicker/CalendarDayButtonEventArgs.cs index a65a97b..cc8fc8d 100644 --- a/src/Ursa/Controls/DateTimePicker/CalendarDayButtonEventArgs.cs +++ b/src/Ursa/Controls/DateTimePicker/CalendarDayButtonEventArgs.cs @@ -2,7 +2,7 @@ namespace Ursa.Controls; -public class CalendarDayButtonEventArgs(DateTime date) : RoutedEventArgs +public class CalendarDayButtonEventArgs(DateTime? date) : RoutedEventArgs { - public DateTime Date { get; private set; } = date; + public DateTime? Date { get; private set; } = date; } \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/CalendarView.cs b/src/Ursa/Controls/DateTimePicker/CalendarView.cs index 547dbec..6cc7094 100644 --- a/src/Ursa/Controls/DateTimePicker/CalendarView.cs +++ b/src/Ursa/Controls/DateTimePicker/CalendarView.cs @@ -4,6 +4,7 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Metadata; using Avalonia.Controls.Primitives; +using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Layout; using Irihi.Avalonia.Shared.Helpers; @@ -408,10 +409,10 @@ public class CalendarView : TemplatedControl private void OnCellDateSelected(object sender, CalendarDayButtonEventArgs e) { - if (e.Date.Month != ContextCalendar.Month) + if (e.Date.HasValue && e.Date.Value.Month != ContextCalendar.Month) { - ContextCalendar.Month = e.Date.Month; - ContextCalendar.Year = e.Date.Year; + ContextCalendar.Month = e.Date.Value.Month; + ContextCalendar.Year = e.Date.Value.Year; ContextCalendar.Day = 1; UpdateDayButtons(); } @@ -575,4 +576,10 @@ public class CalendarView : TemplatedControl button.IsInRange = false; } } + + protected override void OnPointerExited(PointerEventArgs e) + { + base.OnPointerExited(e); + OnDatePreviewed?.Invoke(this, new CalendarDayButtonEventArgs(null)); + } } \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/DateRangePicker.cs b/src/Ursa/Controls/DateTimePicker/DateRangePicker.cs index 1ad45d9..c4556a8 100644 --- a/src/Ursa/Controls/DateTimePicker/DateRangePicker.cs +++ b/src/Ursa/Controls/DateTimePicker/DateRangePicker.cs @@ -1,3 +1,4 @@ +using System.Globalization; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Metadata; @@ -158,14 +159,10 @@ public class DateRangePicker : DatePickerBase { if (SelectedEndDate < e.Date) { - // Select a start date that is out of current range, so clear selection. - // _startCalendar?.ClearSelection(); - // _endCalendar?.ClearSelection(); - SelectedStartDate = null; SelectedEndDate = null; } SetCurrentValue(SelectedStartDateProperty, e.Date); - _startTextBox?.SetValue(TextBox.TextProperty, e.Date.ToString(DisplayFormat ?? "yyyy-MM-dd")); + _startTextBox?.SetValue(TextBox.TextProperty, e.Date?.ToString(DisplayFormat ?? "yyyy-MM-dd")); _start = false; _previewStart = null; _previewEnd = null; @@ -177,20 +174,24 @@ public class DateRangePicker : DatePickerBase { if (SelectedStartDate > e.Date) { - // Select a start date that is out of current range, so clear selection. - // _startCalendar?.ClearSelection(); - // _endCalendar?.ClearSelection(); SelectedStartDate = null; - SelectedEndDate = null; } SetCurrentValue(SelectedEndDateProperty, e.Date); - _endTextBox?.SetValue(TextBox.TextProperty, e.Date.ToString(DisplayFormat ?? "yyyy-MM-dd")); + _endTextBox?.SetValue(TextBox.TextProperty, e.Date?.ToString(DisplayFormat ?? "yyyy-MM-dd")); _start = null; _previewStart = null; _previewEnd = null; _startCalendar?.MarkDates(SelectedStartDate, SelectedEndDate, _previewStart, _previewEnd); _endCalendar?.MarkDates(SelectedStartDate, SelectedEndDate, _previewStart, _previewEnd); - SetCurrentValue(IsDropdownOpenProperty, false); + if (SelectedStartDate is null) + { + _start = true; + _startTextBox?.Focus(); + } + else + { + SetCurrentValue(IsDropdownOpenProperty, false); + } } } @@ -216,8 +217,7 @@ public class DateRangePicker : DatePickerBase if (_endCalendar is not null) { - var date2 = SelectedStartDate ?? SelectedEndDate ?? DateTime.Today; - date2 = SelectedStartDate is null ? date2 : date2.AddMonths(1); + var date2 = SelectedEndDate ?? SelectedStartDate ?? DateTime.Today; _endCalendar.ContextCalendar = new CalendarContext(date2.Year, date2.Month, 1); _endCalendar.UpdateDayButtons(); } @@ -227,8 +227,7 @@ public class DateRangePicker : DatePickerBase _start = false; if (_startCalendar is not null) { - var date2 = SelectedEndDate ?? DateTime.Today; - date2 = date2.AddMonths(-1); + var date2 = SelectedStartDate ?? SelectedEndDate ?? DateTime.Today; _startCalendar.ContextCalendar = new CalendarContext(date2.Year, date2.Month, 1); _startCalendar.UpdateDayButtons(); } @@ -244,7 +243,55 @@ public class DateRangePicker : DatePickerBase private void OnTextChanged(object sender, TextChangedEventArgs e) { - //throw new NotImplementedException(); + if (sender == _startTextBox) + { + OnTextChangedInternal(_startTextBox, SelectedStartDateProperty); + } + else if (sender == _endTextBox) + { + OnTextChangedInternal(_endTextBox, SelectedEndDateProperty); + } + } + + private void OnTextChangedInternal(TextBox? textBox, AvaloniaProperty property) + { + if (string.IsNullOrEmpty(textBox?.Text)) + { + SetCurrentValue(property, null); + _startCalendar?.ClearSelection(); + _endCalendar?.ClearSelection(); + } + else if (DisplayFormat is null || DisplayFormat.Length == 0) + { + if (DateTime.TryParse(textBox?.Text, out var defaultTime)) + { + SetCurrentValue(property, defaultTime); + _startCalendar?.MarkDates(startDate: defaultTime, endDate: defaultTime); + _endCalendar?.MarkDates(startDate: defaultTime, endDate: defaultTime); + } + } + else + { + if (DateTime.TryParseExact(textBox?.Text, DisplayFormat, CultureInfo.CurrentUICulture, DateTimeStyles.None, + out var date)) + { + SetCurrentValue(property, date); + if (_startCalendar is not null) + { + var date1 = SelectedStartDate ?? DateTime.Today; + _startCalendar.ContextCalendar = new CalendarContext(date1.Year, date.Month, 1); + _startCalendar.UpdateDayButtons(); + _startCalendar?.MarkDates(SelectedStartDate, SelectedEndDate, _previewStart, _previewEnd); + } + if (_endCalendar is not null) + { + var date2 = SelectedEndDate ?? DateTime.Today; + _endCalendar.ContextCalendar = new CalendarContext(date2.Year, date2.Month, 1); + _endCalendar.UpdateDayButtons(); + _endCalendar?.MarkDates(SelectedStartDate, SelectedEndDate, _previewStart, _previewEnd); + } + } + } } private void OnTextBoxGetFocus(object sender, GotFocusEventArgs e)