diff --git a/demo/Ursa.Demo/Pages/DatePickerDemo.axaml b/demo/Ursa.Demo/Pages/DatePickerDemo.axaml
index 28ae7c8..ffbd131 100644
--- a/demo/Ursa.Demo/Pages/DatePickerDemo.axaml
+++ b/demo/Ursa.Demo/Pages/DatePickerDemo.axaml
@@ -1,24 +1,28 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/demo/Ursa.Demo/Pages/DatePickerDemo.axaml.cs b/demo/Ursa.Demo/Pages/DatePickerDemo.axaml.cs
index 74214c7..4bb0d49 100644
--- a/demo/Ursa.Demo/Pages/DatePickerDemo.axaml.cs
+++ b/demo/Ursa.Demo/Pages/DatePickerDemo.axaml.cs
@@ -10,14 +10,4 @@ public partial class DatePickerDemo : UserControl
{
InitializeComponent();
}
-
- private void CalendarView_OnOnDateSelected(object? _, CalendarDayButtonEventArgs e)
- {
- Debug.WriteLine("Pressed: "+ e.Date?.ToLongDateString());
- }
-
- private void CalendarView_OnOnDatePreviewed(object? _, CalendarDayButtonEventArgs e)
- {
- Debug.WriteLine("Hovered: "+e.Date?.ToLongDateString());
- }
}
\ No newline at end of file
diff --git a/demo/Ursa.Demo/Pages/DateRangePickerDemo.axaml b/demo/Ursa.Demo/Pages/DateRangePickerDemo.axaml
new file mode 100644
index 0000000..f4f2071
--- /dev/null
+++ b/demo/Ursa.Demo/Pages/DateRangePickerDemo.axaml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demo/Ursa.Demo/Pages/DateRangePickerDemo.axaml.cs b/demo/Ursa.Demo/Pages/DateRangePickerDemo.axaml.cs
new file mode 100644
index 0000000..56acc29
--- /dev/null
+++ b/demo/Ursa.Demo/Pages/DateRangePickerDemo.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace Ursa.Demo.Pages;
+
+public partial class DateRangePickerDemo : UserControl
+{
+ public DateRangePickerDemo()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/demo/Ursa.Demo/Pages/TimePickerDemo.axaml b/demo/Ursa.Demo/Pages/TimePickerDemo.axaml
index 4b849fd..9ffc7fe 100644
--- a/demo/Ursa.Demo/Pages/TimePickerDemo.axaml
+++ b/demo/Ursa.Demo/Pages/TimePickerDemo.axaml
@@ -43,10 +43,6 @@
InnerRightContent="截止"
NeedConfirmation="True"
PanelFormat="{Binding #panelFormat.Text}" />
-
-
diff --git a/demo/Ursa.Demo/Pages/TimeRangePickerDemo.axaml b/demo/Ursa.Demo/Pages/TimeRangePickerDemo.axaml
new file mode 100644
index 0000000..7d98aec
--- /dev/null
+++ b/demo/Ursa.Demo/Pages/TimeRangePickerDemo.axaml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demo/Ursa.Demo/Pages/TimeRangePickerDemo.axaml.cs b/demo/Ursa.Demo/Pages/TimeRangePickerDemo.axaml.cs
new file mode 100644
index 0000000..564a507
--- /dev/null
+++ b/demo/Ursa.Demo/Pages/TimeRangePickerDemo.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace Ursa.Demo.Pages;
+
+public partial class TimeRangePickerDemo : UserControl
+{
+ public TimeRangePickerDemo()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/demo/Ursa.Demo/ViewModels/DatePickerDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/DatePickerDemoViewModel.cs
index 693ab0f..a1bf3c4 100644
--- a/demo/Ursa.Demo/ViewModels/DatePickerDemoViewModel.cs
+++ b/demo/Ursa.Demo/ViewModels/DatePickerDemoViewModel.cs
@@ -7,22 +7,9 @@ namespace Ursa.Demo.ViewModels;
public partial class DatePickerDemoViewModel: ObservableObject
{
[ObservableProperty] private DateTime? _selectedDate;
- [ObservableProperty] private DateTime? _startDate;
- [ObservableProperty] private DateTime? _endDate;
public DatePickerDemoViewModel()
{
SelectedDate = DateTime.Today;
- StartDate = DateTime.Today;
- EndDate = DateTime.Today.AddDays(7);
- }
-
- protected override void OnPropertyChanged(PropertyChangedEventArgs e)
- {
- base.OnPropertyChanged(e);
- if (e.PropertyName == nameof(SelectedDate))
- {
-
- }
}
}
\ No newline at end of file
diff --git a/demo/Ursa.Demo/ViewModels/DateRangePickerDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/DateRangePickerDemoViewModel.cs
new file mode 100644
index 0000000..1bcaa2c
--- /dev/null
+++ b/demo/Ursa.Demo/ViewModels/DateRangePickerDemoViewModel.cs
@@ -0,0 +1,16 @@
+using System;
+using CommunityToolkit.Mvvm.ComponentModel;
+
+namespace Ursa.Demo.ViewModels;
+
+public partial class DateRangePickerDemoViewModel: ObservableObject
+{
+ [ObservableProperty] private DateTime? _startDate;
+ [ObservableProperty] private DateTime? _endDate;
+
+ public DateRangePickerDemoViewModel()
+ {
+ StartDate = DateTime.Today;
+ EndDate = DateTime.Today.AddDays(7);
+ }
+}
\ No newline at end of file
diff --git a/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs b/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs
index 2abaaf4..161df53 100644
--- a/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs
+++ b/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs
@@ -41,6 +41,7 @@ public partial class MainViewViewModel : ViewModelBase
MenuKeys.MenuKeyClassInput => new ClassInputDemoViewModel(),
MenuKeys.MenuKeyClock => new ClockDemoViewModel(),
MenuKeys.MenuKeyDatePicker => new DatePickerDemoViewModel(),
+ MenuKeys.MenuKeyDateRangePicker => new DateRangePickerDemoViewModel(),
MenuKeys.MenuKeyDateTimePicker => new DateTimePickerDemoViewModel(),
MenuKeys.MenuKeyDialog => new DialogDemoViewModel(),
MenuKeys.MenuKeyDisableContainer => new DisableContainerDemoViewModel(),
@@ -75,6 +76,7 @@ public partial class MainViewViewModel : ViewModelBase
MenuKeys.MenuKeyTimeBox => new TimeBoxDemoViewModel(),
MenuKeys.MenuKeyTimeline => new TimelineDemoViewModel(),
MenuKeys.MenuKeyTimePicker => new TimePickerDemoViewModel(),
+ MenuKeys.MenuKeyTimeRangePicker => new TimeRangePickerDemoViewModel(),
MenuKeys.MenuKeyToast => new ToastDemoViewModel(),
MenuKeys.MenuKeyToolBar => new ToolBarDemoViewModel(),
MenuKeys.MenuKeyTreeComboBox => new TreeComboBoxDemoViewModel(),
diff --git a/demo/Ursa.Demo/ViewModels/MenuViewModel.cs b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs
index b044516..fde221b 100644
--- a/demo/Ursa.Demo/ViewModels/MenuViewModel.cs
+++ b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs
@@ -52,10 +52,12 @@ public class MenuViewModel : ViewModelBase
{
MenuHeader = "Date & Time", Children = new ObservableCollection
{
- new() { MenuHeader = "Date Picker", Key = MenuKeys.MenuKeyDatePicker },
- new() { MenuHeader = "Date Time Picker", Key = MenuKeys.MenuKeyDateTimePicker },
+ new() { MenuHeader = "Date Picker", Key = MenuKeys.MenuKeyDatePicker, Status = "Updated" },
+ new() { MenuHeader = "Date Range Picker", Key = MenuKeys.MenuKeyDateRangePicker, Status = "Updated" },
+ new() { MenuHeader = "Date Time Picker", Key = MenuKeys.MenuKeyDateTimePicker, Status = "Updated" },
new() { MenuHeader = "Time Box", Key = MenuKeys.MenuKeyTimeBox },
- new() { MenuHeader = "TimePicker", Key = MenuKeys.MenuKeyTimePicker },
+ new() { MenuHeader = "Time Picker", Key = MenuKeys.MenuKeyTimePicker, Status = "Updated" },
+ new() { MenuHeader = "Time Range Picker", Key = MenuKeys.MenuKeyTimeRangePicker, Status = "Updated" },
new() { MenuHeader = "Clock", Key = MenuKeys.MenuKeyClock }
}
},
@@ -108,6 +110,7 @@ public static class MenuKeys
public const string MenuKeyClassInput = "Class Input";
public const string MenuKeyClock = "Clock";
public const string MenuKeyDatePicker = "DatePicker";
+ public const string MenuKeyDateRangePicker = "DateRangePicker";
public const string MenuKeyDateTimePicker = "DateTimePicker";
public const string MenuKeyDialog = "Dialog";
public const string MenuKeyDisableContainer = "DisableContainer";
@@ -142,6 +145,7 @@ public static class MenuKeys
public const string MenuKeyTimeBox = "TimeBox";
public const string MenuKeyTimeline = "Timeline";
public const string MenuKeyTimePicker = "TimePicker";
+ public const string MenuKeyTimeRangePicker = "TimeRangePicker";
public const string MenuKeyToast = "Toast";
public const string MenuKeyToolBar = "ToolBar";
public const string MenuKeyTreeComboBox = "TreeComboBox";
diff --git a/demo/Ursa.Demo/ViewModels/TimePickerDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/TimePickerDemoViewModel.cs
index 7b93e1a..fed5690 100644
--- a/demo/Ursa.Demo/ViewModels/TimePickerDemoViewModel.cs
+++ b/demo/Ursa.Demo/ViewModels/TimePickerDemoViewModel.cs
@@ -6,13 +6,9 @@ namespace Ursa.Demo.ViewModels;
public partial class TimePickerDemoViewModel: ObservableObject
{
[ObservableProperty] private TimeSpan? _time;
- [ObservableProperty] private TimeSpan? _startTime;
- [ObservableProperty] private TimeSpan? _endTime;
-
+
public TimePickerDemoViewModel()
{
Time = new TimeSpan(12, 20, 0);
- StartTime = new TimeSpan(8, 21, 0);
- EndTime = new TimeSpan(18, 22, 0);
}
}
\ No newline at end of file
diff --git a/demo/Ursa.Demo/ViewModels/TimeRangePickerDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/TimeRangePickerDemoViewModel.cs
new file mode 100644
index 0000000..5369eaf
--- /dev/null
+++ b/demo/Ursa.Demo/ViewModels/TimeRangePickerDemoViewModel.cs
@@ -0,0 +1,16 @@
+using System;
+using CommunityToolkit.Mvvm.ComponentModel;
+
+namespace Ursa.Demo.ViewModels;
+
+public partial class TimeRangePickerDemoViewModel: ObservableObject
+{
+ [ObservableProperty] private TimeSpan? _startTime;
+ [ObservableProperty] private TimeSpan? _endTime;
+
+ public TimeRangePickerDemoViewModel()
+ {
+ StartTime = new TimeSpan(8, 21, 0);
+ EndTime = new TimeSpan(18, 22, 0);
+ }
+}
\ No newline at end of file
diff --git a/src/Ursa.Themes.Semi/Controls/DateRangePicker.axaml b/src/Ursa.Themes.Semi/Controls/DateRangePicker.axaml
index c9ba2ed..db9c77b 100644
--- a/src/Ursa.Themes.Semi/Controls/DateRangePicker.axaml
+++ b/src/Ursa.Themes.Semi/Controls/DateRangePicker.axaml
@@ -26,7 +26,7 @@
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}" />
-
+
-
diff --git a/src/Ursa/Controls/DateTimePicker/DatePicker.cs b/src/Ursa/Controls/DateTimePicker/DatePicker.cs
index 03f673f..256cb7a 100644
--- a/src/Ursa/Controls/DateTimePicker/DatePicker.cs
+++ b/src/Ursa/Controls/DateTimePicker/DatePicker.cs
@@ -129,26 +129,7 @@ public class DatePicker: DatePickerBase, IClearControl
}
else
{
- if (DateTime.TryParseExact(_textBox?.Text, DisplayFormat, CultureInfo.CurrentUICulture, DateTimeStyles.None,
- out var date))
- {
- SetCurrentValue(SelectedDateProperty, date);
- if (_calendar is not null)
- {
- _calendar.ContextDate = _calendar.ContextDate.With(year: date.Year, month: date.Month);
- _calendar.UpdateDayButtons();
- }
- _calendar?.MarkDates(startDate: date, endDate: date);
- }
- else
- {
- SetCurrentValue(SelectedDateProperty, null);
- if (!fromText)
- {
- _textBox?.SetValue(TextBox.TextProperty, null);
- }
- _calendar?.ClearSelection();
- }
+ CommitInput(!fromText);
}
}
@@ -192,6 +173,13 @@ public class DatePicker: DatePickerBase, IClearControl
case Key.Tab:
SetCurrentValue(IsDropdownOpenProperty, false);
return;
+ case Key.Enter:
+ {
+ SetCurrentValue(IsDropdownOpenProperty, false);
+ CommitInput(true);
+ e.Handled = true;
+ return;
+ }
default:
base.OnKeyDown(e);
break;
@@ -219,6 +207,7 @@ public class DatePicker: DatePickerBase, IClearControl
{
return;
}
+ CommitInput(true);
SetCurrentValue(IsDropdownOpenProperty, false);
}
@@ -230,12 +219,33 @@ public class DatePicker: DatePickerBase, IClearControl
if (hasFocus)
{
-
if (!wasFocused && _textBox != null)
{
_textBox.Focus();
- _textBox.SelectAll();
}
}
}
+
+ private void CommitInput(bool clearWhenInvalid)
+ {
+ if (DateTime.TryParseExact(_textBox?.Text, DisplayFormat, CultureInfo.CurrentUICulture, DateTimeStyles.None,
+ out var date))
+ {
+ SetCurrentValue(SelectedDateProperty, date);
+ if (_calendar is not null)
+ {
+ _calendar.ContextDate = _calendar.ContextDate.With(year: date.Year, month: date.Month);
+ _calendar.UpdateDayButtons();
+ }
+ _calendar?.MarkDates(startDate: date, endDate: date);
+ }
+ else
+ {
+ if (clearWhenInvalid)
+ {
+ SetCurrentValue(SelectedDateProperty, null);
+ }
+ _calendar?.ClearSelection();
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Ursa/Controls/DateTimePicker/DateRangePicker.cs b/src/Ursa/Controls/DateTimePicker/DateRangePicker.cs
index 56968f7..2bef08b 100644
--- a/src/Ursa/Controls/DateTimePicker/DateRangePicker.cs
+++ b/src/Ursa/Controls/DateTimePicker/DateRangePicker.cs
@@ -9,6 +9,7 @@ using Avalonia.Interactivity;
using Irihi.Avalonia.Shared.Common;
using Irihi.Avalonia.Shared.Contracts;
using Irihi.Avalonia.Shared.Helpers;
+using Calendar = Avalonia.Controls.Calendar;
namespace Ursa.Controls;
@@ -53,6 +54,7 @@ public class DateRangePicker : DatePickerBase, IClearControl
static DateRangePicker()
{
+ FocusableProperty.OverrideDefaultValue(true);
SelectedStartDateProperty.Changed.AddClassHandler((picker, args) =>
picker.OnSelectionChanged(args));
SelectedEndDateProperty.Changed.AddClassHandler((picker, args) =>
@@ -279,7 +281,6 @@ public class DateRangePicker : DatePickerBase, IClearControl
private void OnButtonClick(object? sender, RoutedEventArgs e)
{
- Focus(NavigationMethod.Pointer);
SetCurrentValue(IsDropdownOpenProperty, !IsDropdownOpen);
_startTextBox?.Focus();
// _start = true;
@@ -456,9 +457,111 @@ public class DateRangePicker : DatePickerBase, IClearControl
}
return;
}
+ case Key.Enter:
+ {
+ SetCurrentValue(IsDropdownOpenProperty, false);
+ CommitInput(true);
+ e.Handled = true;
+ return;
+ }
default:
base.OnKeyDown(e);
break;
}
}
+
+ protected override void OnGotFocus(GotFocusEventArgs e)
+ {
+ base.OnGotFocus(e);
+ FocusChanged(IsKeyboardFocusWithin);
+ }
+
+ protected override void OnLostFocus(RoutedEventArgs e)
+ {
+ base.OnLostFocus(e);
+ FocusChanged(IsKeyboardFocusWithin);
+ var top = TopLevel.GetTopLevel(this);
+ var element = top?.FocusManager?.GetFocusedElement();
+ if (element is Visual v && _popup?.IsInsidePopup(v)==true)
+ {
+ return;
+ }
+
+ if (element == _startTextBox || element == _endTextBox)
+ {
+ return;
+ }
+ CommitInput(true);
+ SetCurrentValue(IsDropdownOpenProperty, false);
+ }
+
+ private bool _isFocused;
+ private void FocusChanged(bool hasFocus)
+ {
+ bool wasFocused = _isFocused;
+ _isFocused = hasFocus;
+
+ if (hasFocus)
+ {
+ if (!wasFocused && _startTextBox != null)
+ {
+ _startTextBox.Focus();
+ _start = true;
+ }
+ }
+ }
+
+ private void CommitInput(bool clearWhenInvalid)
+ {
+ DateTime? startDate = null;
+ DateTime? endDate = null;
+ if (DateTime.TryParseExact(_startTextBox?.Text, DisplayFormat, CultureInfo.CurrentUICulture, DateTimeStyles.None,
+ out var localStartDate))
+ {
+ startDate = localStartDate;
+ SetCurrentValue(SelectedStartDateProperty, localStartDate);
+ if (_startCalendar is not null)
+ {
+ _startCalendar.ContextDate = _startCalendar.ContextDate.With(year: localStartDate.Year, month: localStartDate.Month);
+ _startCalendar.UpdateDayButtons();
+ }
+ }
+ else
+ {
+ if (clearWhenInvalid)
+ {
+ SetCurrentValue(SelectedStartDateProperty, null);
+ }
+
+ }
+ if (DateTime.TryParseExact(_endTextBox?.Text, DisplayFormat, CultureInfo.CurrentUICulture, DateTimeStyles.None,
+ out var localEndDate))
+ {
+ endDate = localEndDate;
+ SetCurrentValue(SelectedEndDateProperty, localEndDate);
+ if (_endCalendar is not null)
+ {
+ _endCalendar.ContextDate = _endCalendar.ContextDate.With(year: localEndDate.Year, month: localEndDate.Month);
+ _endCalendar.UpdateDayButtons();
+ }
+ }
+ else
+ {
+ if (clearWhenInvalid)
+ {
+ SetCurrentValue(SelectedEndDateProperty, null);
+ }
+ }
+ if (startDate is null || endDate is null)
+ {
+ _startCalendar?.ClearSelection();
+ _endCalendar?.ClearSelection();
+ }
+ else
+ {
+ _startCalendar?.MarkDates(startDate: startDate, endDate: endDate);
+ _endCalendar?.MarkDates(startDate: startDate, endDate: endDate);
+ }
+ }
+
}
\ No newline at end of file
diff --git a/src/Ursa/Controls/DateTimePicker/DateTimePicker.cs b/src/Ursa/Controls/DateTimePicker/DateTimePicker.cs
index 22793ac..dca00aa 100644
--- a/src/Ursa/Controls/DateTimePicker/DateTimePicker.cs
+++ b/src/Ursa/Controls/DateTimePicker/DateTimePicker.cs
@@ -41,10 +41,12 @@ public class DateTimePicker : DatePickerBase
private Button? _button;
private CalendarView? _calendar;
private TextBox? _textBox;
+ private Popup? _popup;
private TimePickerPresenter? _timePickerPresenter;
static DateTimePicker()
{
+ FocusableProperty.OverrideDefaultValue(true);
DisplayFormatProperty.OverrideDefaultValue(CultureInfo.InvariantCulture.DateTimeFormat.FullDateTimePattern);
SelectedDateProperty.Changed.AddClassHandler((picker, args) =>
picker.OnSelectionChanged(args));
@@ -102,19 +104,17 @@ public class DateTimePicker : DatePickerBase
base.OnApplyTemplate(e);
GotFocusEvent.RemoveHandler(OnTextBoxGetFocus, _textBox);
TextBox.TextChangedEvent.RemoveHandler(OnTextChanged, _textBox);
- PointerPressedEvent.RemoveHandler(OnTextBoxPointerPressed, _textBox);
Button.ClickEvent.RemoveHandler(OnButtonClick, _button);
CalendarView.DateSelectedEvent.RemoveHandler(OnDateSelected, _calendar);
TimePickerPresenter.SelectedTimeChangedEvent.RemoveHandler(OnTimeSelectedChanged, _timePickerPresenter);
_button = e.NameScope.Find