diff --git a/src/Compatibility/Core/src/WinUI/DatePickerRenderer.cs b/src/Compatibility/Core/src/WinUI/DatePickerRenderer.cs index 08771edfa0ad..a6bf5b191f5f 100644 --- a/src/Compatibility/Core/src/WinUI/DatePickerRenderer.cs +++ b/src/Compatibility/Core/src/WinUI/DatePickerRenderer.cs @@ -120,6 +120,7 @@ protected override void OnElementPropertyChanged(object sender, PropertyChangedE protected override bool PreventGestureBubbling { get; set; } = true; + [PortHandler] void OnControlDateChanged(object sender, DatePickerValueChangedEventArgs e) { if (Element == null) @@ -237,11 +238,13 @@ void UpdateFlowDirection() Control.UpdateFlowDirection(Element); } + [PortHandler] void UpdateCharacterSpacing() { Control.CharacterSpacing = Element.CharacterSpacing.ToEm(); } + [PortHandler] void UpdateFont() { if (Control == null) @@ -275,12 +278,14 @@ void UpdateFont() _fontApplied = true; } + [PortHandler] void UpdateMaximumDate() { if (Element != null && Control != null) Control.MaxYear = new DateTimeOffset(new DateTime(Element.MaximumDate.Ticks, DateTimeKind.Unspecified)); } + [PortHandler] void UpdateMinimumDate() { DateTime mindate = Element.MinimumDate; diff --git a/src/Compatibility/Core/src/WinUI/Extensions.cs b/src/Compatibility/Core/src/WinUI/Extensions.cs index 22fc585b019e..7300005c9227 100644 --- a/src/Compatibility/Core/src/WinUI/Extensions.cs +++ b/src/Compatibility/Core/src/WinUI/Extensions.cs @@ -85,6 +85,7 @@ internal static UwpScrollBarVisibility ToUwpScrollBarVisibility(this ScrollBarVi } } + [PortHandler] public static T Clamp(this T value, T min, T max) where T : IComparable { if (value.CompareTo(min) < 0) diff --git a/src/Core/src/Handlers/DatePicker/DatePickerHandler.Windows.cs b/src/Core/src/Handlers/DatePicker/DatePickerHandler.Windows.cs index cb382688417c..fd22e0615d10 100644 --- a/src/Core/src/Handlers/DatePicker/DatePickerHandler.Windows.cs +++ b/src/Core/src/Handlers/DatePicker/DatePickerHandler.Windows.cs @@ -1,4 +1,4 @@ -using System; +#nullable enable using Microsoft.UI.Xaml.Controls; namespace Microsoft.Maui.Handlers @@ -7,27 +7,70 @@ public partial class DatePickerHandler : ViewHandler { protected override DatePicker CreateNativeView() => new DatePicker(); - [MissingMapper] - public static void MapFormat(DatePickerHandler handler, IDatePicker datePicker) { } + protected override void ConnectHandler(DatePicker nativeView) + { + nativeView.DateChanged += OnControlDateChanged; + } + + protected override void DisconnectHandler(DatePicker nativeView) + { + nativeView.DateChanged -= OnControlDateChanged; + } + + public static void MapFormat(DatePickerHandler handler, IDatePicker datePicker) + { + handler.NativeView?.UpdateDate(datePicker); + } public static void MapDate(DatePickerHandler handler, IDatePicker datePicker) { handler.NativeView?.UpdateDate(datePicker); } - [MissingMapper] - public static void MapMinimumDate(DatePickerHandler handler, IDatePicker datePicker) { } + public static void MapMinimumDate(DatePickerHandler handler, IDatePicker datePicker) + { + handler.NativeView?.UpdateMinimumDate(datePicker); + } - [MissingMapper] - public static void MapMaximumDate(DatePickerHandler handler, IDatePicker datePicker) { } + public static void MapMaximumDate(DatePickerHandler handler, IDatePicker datePicker) + { + handler.NativeView?.UpdateMaximumDate(datePicker); + } - [MissingMapper] - public static void MapCharacterSpacing(DatePickerHandler handler, IDatePicker datePicker) { } + public static void MapCharacterSpacing(DatePickerHandler handler, IDatePicker datePicker) + { + handler.NativeView?.UpdateCharacterSpacing(datePicker); + } - [MissingMapper] - public static void MapFont(DatePickerHandler handler, IDatePicker datePicker) { } + public static void MapFont(DatePickerHandler handler, IDatePicker datePicker) + { + var fontManager = handler.GetRequiredService(); + + handler.NativeView?.UpdateFont(datePicker, fontManager); + } [MissingMapper] public static void MapTextColor(DatePickerHandler handler, IDatePicker datePicker) { } + + void OnControlDateChanged(object? sender, DatePickerValueChangedEventArgs e) + { + if (VirtualView == null) + return; + + if (VirtualView.Date.CompareTo(e.NewDate.Date) != 0) + { + var date = e.NewDate.Date.Clamp(VirtualView.MinimumDate, VirtualView.MaximumDate); + VirtualView.Date = date; + + // Set the control date-time to clamped value, if it exceeded the limits at the time of installation. + if (date != e.NewDate.Date) + { + NativeView?.UpdateDate(date); + NativeView?.UpdateLayout(); + } + + VirtualView.InvalidateMeasure(); + } + } } } \ No newline at end of file diff --git a/src/Core/src/Platform/CompareExtensions.cs b/src/Core/src/Platform/CompareExtensions.cs new file mode 100644 index 000000000000..059e7bbc339a --- /dev/null +++ b/src/Core/src/Platform/CompareExtensions.cs @@ -0,0 +1,21 @@ +using System; + +namespace Microsoft.Maui +{ + public static class CompareExtensions + { + public static T Clamp(this T value, T min, T max) where T : IComparable + { + if (max.CompareTo(min) < 0) + return max; + + if (value.CompareTo(min) < 0) + return min; + + if (value.CompareTo(max) > 0) + return max; + + return value; + } + } +} \ No newline at end of file diff --git a/src/Core/src/Platform/Windows/DatePickerExtensions.cs b/src/Core/src/Platform/Windows/DatePickerExtensions.cs index 3951a72d6582..36a33670f7fa 100644 --- a/src/Core/src/Platform/Windows/DatePickerExtensions.cs +++ b/src/Core/src/Platform/Windows/DatePickerExtensions.cs @@ -9,13 +9,49 @@ public static class DatePickerExtensions public static void UpdateDate(this DatePicker nativeDatePicker, IDatePicker datePicker) { var date = datePicker.Date; - nativeDatePicker.Date = new DateTimeOffset(new DateTime(date.Ticks, DateTimeKind.Unspecified)); + nativeDatePicker.UpdateDate(date); nativeDatePicker.UpdateDay(datePicker); nativeDatePicker.UpdateMonth(datePicker); nativeDatePicker.UpdateYear(datePicker); } + public static void UpdateDate(this DatePicker nativeDatePicker, DateTime dateTime) + { + nativeDatePicker.Date = new DateTimeOffset(new DateTime(dateTime.Ticks, DateTimeKind.Unspecified)); + } + + public static void UpdateMinimumDate(this DatePicker nativeDatePicker, IDatePicker datePicker) + { + DateTime mindate = datePicker.MinimumDate; + + try + { + nativeDatePicker.MinYear = new DateTimeOffset(new DateTime(datePicker.MinimumDate.Ticks, DateTimeKind.Unspecified)); + } + catch (ArgumentOutOfRangeException) + { + // This will be thrown when mindate equals DateTime.MinValue and the UTC offset is positive + // because the resulting DateTimeOffset.UtcDateTime will be out of range. In that case let's + // specify the Kind as UTC so there is no offset. + mindate = DateTime.SpecifyKind(mindate, DateTimeKind.Utc); + nativeDatePicker.MinYear = new DateTimeOffset(mindate); + } + } + + public static void UpdateMaximumDate(this DatePicker nativeDatePicker, IDatePicker datePicker) + { + nativeDatePicker.MaxYear = new DateTimeOffset(new DateTime(datePicker.MaximumDate.Ticks, DateTimeKind.Unspecified)); + } + + public static void UpdateCharacterSpacing(this DatePicker nativeDatePicker, IDatePicker datePicker) + { + nativeDatePicker.CharacterSpacing = datePicker.CharacterSpacing.ToEm(); + } + + public static void UpdateFont(this DatePicker nativeDatePicker, IDatePicker datePicker, IFontManager fontManager) => + nativeDatePicker.UpdateFont(datePicker.Font, fontManager); + internal static void UpdateDay(this DatePicker nativeDatePicker, IDatePicker datePicker) { nativeDatePicker.DayVisible = true; diff --git a/src/Core/src/Platform/Windows/TextBoxExtensions.cs b/src/Core/src/Platform/Windows/TextBoxExtensions.cs index 3b57d624469f..abdbca56a651 100644 --- a/src/Core/src/Platform/Windows/TextBoxExtensions.cs +++ b/src/Core/src/Platform/Windows/TextBoxExtensions.cs @@ -47,8 +47,8 @@ public static void UpdateFont(this MauiTextBox nativeControl, Font font, IFontMa { nativeControl.FontSize = fontManager.GetFontSize(font); nativeControl.FontFamily = fontManager.GetFontFamily(font); - nativeControl.FontStyle = font.FontAttributes.ToFontStyle(); - nativeControl.FontWeight = font.FontAttributes.ToFontWeight(); + nativeControl.FontStyle = font.ToFontStyle(); + nativeControl.FontWeight = font.ToFontWeight(); } public static void UpdateIsReadOnly(this MauiTextBox textBox, IEditor editor)