From ccc1b07b139faae6736d76241489675d88208cf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Su=C3=A1rez=20Ruiz?= Date: Mon, 19 Apr 2021 16:35:38 +0200 Subject: [PATCH 1/6] Implement PickerHandler in WinUI --- .../Core/src/Windows/Extensions.cs | 2 +- .../Core/src/Windows/PickerRenderer.cs | 6 + .../Handlers/Picker/PickerHandler.Windows.cs | 74 ++++- .../Windows/CharacterSpacingExtensions.cs | 12 + .../src/Platform/Windows/ColorConverter.cs | 27 ++ src/Core/src/Platform/Windows/MauiCombobox.cs | 25 ++ .../src/Platform/Windows/PickerExtensions.cs | 42 +++ .../Windows/Styles/MauiComboBoxStyle.xaml | 262 ++++++++++++++++++ .../Platform/Windows/Styles/Resources.xaml | 5 +- .../LockableObservableListWrapper.cs | 9 +- 10 files changed, 443 insertions(+), 21 deletions(-) create mode 100644 src/Core/src/Platform/Windows/CharacterSpacingExtensions.cs create mode 100644 src/Core/src/Platform/Windows/ColorConverter.cs create mode 100644 src/Core/src/Platform/Windows/MauiCombobox.cs create mode 100644 src/Core/src/Platform/Windows/PickerExtensions.cs create mode 100644 src/Core/src/Platform/Windows/Styles/MauiComboBoxStyle.xaml rename src/{Controls/src/Core => Core/src/Primitives}/LockableObservableListWrapper.cs (90%) diff --git a/src/Compatibility/Core/src/Windows/Extensions.cs b/src/Compatibility/Core/src/Windows/Extensions.cs index e6c86643eba1..22fc585b019e 100644 --- a/src/Compatibility/Core/src/Windows/Extensions.cs +++ b/src/Compatibility/Core/src/Windows/Extensions.cs @@ -94,7 +94,7 @@ public static T Clamp(this T value, T min, T max) where T : IComparable return value; } - + [PortHandler] internal static int ToEm(this double pt) { return Convert.ToInt32( pt * 0.0624f * 1000); //Coefficient for converting Pt to Em. The value is uniform spacing between characters, in units of 1/1000 of an em. diff --git a/src/Compatibility/Core/src/Windows/PickerRenderer.cs b/src/Compatibility/Core/src/Windows/PickerRenderer.cs index 3100a5005b87..eb8f7b4f674e 100644 --- a/src/Compatibility/Core/src/Windows/PickerRenderer.cs +++ b/src/Compatibility/Core/src/Windows/PickerRenderer.cs @@ -124,6 +124,7 @@ void ControlOnOpenAnimationCompleted(object sender, EventArgs eventArgs) } } + [PortHandler] void OnControlSelectionChanged(object sender, WSelectionChangedEventArgs e) { if (Element != null) @@ -172,11 +173,13 @@ void StartAnimationRefresh() }); } + [PortHandler] void UpdateCharacterSpacing() { Control.CharacterSpacing = Element.CharacterSpacing.ToEm(); } + [PortHandler] void UpdateFont() { if (Control == null) @@ -210,17 +213,20 @@ void UpdateFont() _fontApplied = true; } + [PortHandler] void UpdateSelectedIndex() { Control.SelectedIndex = Element.SelectedIndex; } + [PortHandler] void UpdateTextColor() { Color color = Element.TextColor; Control.Foreground = color.IsDefault() ? (_defaultBrush ?? color.ToBrush()) : color.ToBrush(); } + [PortHandler] void UpdateTitle() { Control.Header = null; diff --git a/src/Core/src/Handlers/Picker/PickerHandler.Windows.cs b/src/Core/src/Handlers/Picker/PickerHandler.Windows.cs index 53b43f8dd590..7c347806537d 100644 --- a/src/Core/src/Handlers/Picker/PickerHandler.Windows.cs +++ b/src/Core/src/Handlers/Picker/PickerHandler.Windows.cs @@ -1,25 +1,71 @@ -using System; -using Microsoft.UI.Xaml.Controls; +#nullable enable +using WBrush = Microsoft.UI.Xaml.Media.Brush; +using WSelectionChangedEventArgs = Microsoft.UI.Xaml.Controls.SelectionChangedEventArgs; namespace Microsoft.Maui.Handlers { - public partial class PickerHandler : ViewHandler + public partial class PickerHandler : ViewHandler { - protected override ComboBox CreateNativeView() => new ComboBox(); + WBrush? _defaultForeground; - [MissingMapper] - public static void MapTitle(PickerHandler handler, IPicker view) { } + protected override MauiComboBox CreateNativeView() + { + var nativePicker = new MauiComboBox(); + + if (VirtualView != null) + nativePicker.ItemsSource = ((LockableObservableListWrapper)VirtualView.Items)._list; + + return nativePicker; + } - [MissingMapper] - public static void MapSelectedIndex(PickerHandler handler, IPicker view) { } + protected override void ConnectHandler(MauiComboBox nativeView) + { + nativeView.SelectionChanged += OnControlSelectionChanged; + } - [MissingMapper] - public static void MapCharacterSpacing(PickerHandler handler, IPicker view) { } + protected override void DisconnectHandler(MauiComboBox nativeView) + { + nativeView.SelectionChanged -= OnControlSelectionChanged; + } - [MissingMapper] - public static void MapFont(PickerHandler handler, IPicker view) { } + protected override void SetupDefaults(MauiComboBox nativeView) + { + _defaultForeground = nativeView.Foreground; - [MissingMapper] - public static void MapTextColor(PickerHandler handler, IPicker view) { } + base.SetupDefaults(nativeView); + } + + public static void MapTitle(PickerHandler handler, IPicker picker) + { + handler.NativeView?.UpdateTitle(picker); + } + + public static void MapSelectedIndex(PickerHandler handler, IPicker picker) + { + handler.NativeView?.UpdateSelectedIndex(picker); + } + + public static void MapCharacterSpacing(PickerHandler handler, IPicker picker) + { + handler.NativeView?.UpdateCharacterSpacing(picker); + } + + public static void MapFont(PickerHandler handler, IPicker picker) + { + var fontManager = handler.GetRequiredService(); + + handler.NativeView?.UpdateFont(picker, fontManager); + } + + public static void MapTextColor(PickerHandler handler, IPicker picker) + { + handler.NativeView?.UpdateTextColor(picker, handler._defaultForeground); + } + + void OnControlSelectionChanged(object? sender, WSelectionChangedEventArgs e) + { + if (VirtualView != null && NativeView != null) + VirtualView.SelectedIndex = NativeView.SelectedIndex; + } } } \ No newline at end of file diff --git a/src/Core/src/Platform/Windows/CharacterSpacingExtensions.cs b/src/Core/src/Platform/Windows/CharacterSpacingExtensions.cs new file mode 100644 index 000000000000..d6a6469d4c3e --- /dev/null +++ b/src/Core/src/Platform/Windows/CharacterSpacingExtensions.cs @@ -0,0 +1,12 @@ +using System; + +namespace Microsoft.Maui +{ + public static class CharacterSpacingExtensions + { + public static int ToEm(this double pt) + { + return Convert.ToInt32(pt * 0.0624f * 1000); // Coefficient for converting Pt to Em. The value is uniform spacing between characters, in units of 1/1000 of an em. + } + } +} \ No newline at end of file diff --git a/src/Core/src/Platform/Windows/ColorConverter.cs b/src/Core/src/Platform/Windows/ColorConverter.cs new file mode 100644 index 000000000000..1203ab39e94f --- /dev/null +++ b/src/Core/src/Platform/Windows/ColorConverter.cs @@ -0,0 +1,27 @@ +using System; +using Microsoft.UI; +using WBrush = Microsoft.UI.Xaml.Media.Brush; +using WSolidColorBrush = Microsoft.UI.Xaml.Media.SolidColorBrush; + +namespace Microsoft.Maui +{ + public sealed class ColorConverter : UI.Xaml.Data.IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + var color = (Graphics.Color)value; + var defaultColorKey = (string)parameter; + + WBrush defaultBrush = defaultColorKey != null ? + (WBrush)UI.Xaml.Application.Current.Resources[defaultColorKey] : + new WSolidColorBrush(Colors.Transparent); + + return color.IsDefault() ? defaultBrush : color.ToNative(); + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/Core/src/Platform/Windows/MauiCombobox.cs b/src/Core/src/Platform/Windows/MauiCombobox.cs new file mode 100644 index 000000000000..575afa7967de --- /dev/null +++ b/src/Core/src/Platform/Windows/MauiCombobox.cs @@ -0,0 +1,25 @@ +using Microsoft.UI.Xaml.Controls; + +namespace Microsoft.Maui +{ + public class MauiComboBox : ComboBox + { + public MauiComboBox() + { + DefaultStyleKey = typeof(MauiComboBox); + + DropDownOpened += FormsComboBoxDropDownOpened; + SelectionChanged += FormsComboBoxSelectionChanged; + } + + void FormsComboBoxDropDownOpened(object? sender, object e) + { + MinWidth = ActualWidth; + } + + void FormsComboBoxSelectionChanged(object? sender, SelectionChangedEventArgs e) + { + MinWidth = 0; + } + } +} \ No newline at end of file diff --git a/src/Core/src/Platform/Windows/PickerExtensions.cs b/src/Core/src/Platform/Windows/PickerExtensions.cs new file mode 100644 index 000000000000..9201546a87ea --- /dev/null +++ b/src/Core/src/Platform/Windows/PickerExtensions.cs @@ -0,0 +1,42 @@ +using Microsoft.Maui.Graphics; +using Microsoft.UI.Xaml.Controls; +using WBrush = Microsoft.UI.Xaml.Media.Brush; + +namespace Microsoft.Maui +{ + public static class PickerExtensions + { + public static void UpdateTitle(this MauiComboBox nativeComboBox, IPicker picker) + { + nativeComboBox.Header = null; + + nativeComboBox.HeaderTemplate = string.IsNullOrEmpty(picker.Title) ? null : + (UI.Xaml.DataTemplate)UI.Xaml.Application.Current.Resources["ComboBoxHeader"]; + + nativeComboBox.DataContext = picker; + } + public static void UpdateTextColor(this MauiComboBox nativeComboBox, IPicker picker) + { + nativeComboBox.UpdateTextColor(picker, null); + } + + public static void UpdateTextColor(this MauiComboBox nativeComboBox, IPicker picker, WBrush? defaultForeground) + { + Color color = picker.TextColor; + nativeComboBox.Foreground = color.IsDefault() ? (defaultForeground ?? color.ToNative()) : color.ToNative(); + } + + public static void UpdateSelectedIndex(this MauiComboBox nativeComboBox, IPicker picker) + { + nativeComboBox.SelectedIndex = picker.SelectedIndex; + } + + public static void UpdateCharacterSpacing(this MauiComboBox nativeComboBox, IPicker picker) + { + nativeComboBox.CharacterSpacing = picker.CharacterSpacing.ToEm(); + } + + public static void UpdateFont(this ComboBox nativeComboBox, IPicker picker, IFontManager fontManager) => + nativeComboBox.UpdateFont(picker.Font, fontManager); + } +} \ No newline at end of file diff --git a/src/Core/src/Platform/Windows/Styles/MauiComboBoxStyle.xaml b/src/Core/src/Platform/Windows/Styles/MauiComboBoxStyle.xaml new file mode 100644 index 000000000000..24c9b6285fa9 --- /dev/null +++ b/src/Core/src/Platform/Windows/Styles/MauiComboBoxStyle.xaml @@ -0,0 +1,262 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/Core/src/Platform/Windows/Styles/Resources.xaml b/src/Core/src/Platform/Windows/Styles/Resources.xaml index eace73f4a171..9f8f62fb86f2 100644 --- a/src/Core/src/Platform/Windows/Styles/Resources.xaml +++ b/src/Core/src/Platform/Windows/Styles/Resources.xaml @@ -5,7 +5,10 @@ x:Class="Microsoft.Maui.Resources"> + - + + + diff --git a/src/Controls/src/Core/LockableObservableListWrapper.cs b/src/Core/src/Primitives/LockableObservableListWrapper.cs similarity index 90% rename from src/Controls/src/Core/LockableObservableListWrapper.cs rename to src/Core/src/Primitives/LockableObservableListWrapper.cs index b431c9354e6b..fa1c4bdc70ac 100644 --- a/src/Controls/src/Core/LockableObservableListWrapper.cs +++ b/src/Core/src/Primitives/LockableObservableListWrapper.cs @@ -1,26 +1,25 @@ +#nullable enable using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; -using System.Runtime.CompilerServices; -using Microsoft.Maui.Controls.Internals; -namespace Microsoft.Maui.Controls.Internals +namespace Microsoft.Maui { [EditorBrowsable(EditorBrowsableState.Never)] public class LockableObservableListWrapper : IList, ICollection, INotifyCollectionChanged, INotifyPropertyChanged, IReadOnlyList, IReadOnlyCollection, IEnumerable, IEnumerable { public readonly ObservableCollection _list = new ObservableCollection(); - event NotifyCollectionChangedEventHandler INotifyCollectionChanged.CollectionChanged + event NotifyCollectionChangedEventHandler? INotifyCollectionChanged.CollectionChanged { add { ((INotifyCollectionChanged)_list).CollectionChanged += value; } remove { ((INotifyCollectionChanged)_list).CollectionChanged -= value; } } - event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged + event PropertyChangedEventHandler? INotifyPropertyChanged.PropertyChanged { add { ((INotifyPropertyChanged)_list).PropertyChanged += value; } remove { ((INotifyPropertyChanged)_list).PropertyChanged -= value; } From ce686d7f2248131a705a14f590dca83aa4f01846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Su=C3=A1rez=20Ruiz?= Date: Mon, 19 Apr 2021 17:10:40 +0200 Subject: [PATCH 2/6] Enab le nullable in some classes --- src/Core/src/Platform/iOS/MauiPicker.cs | 3 ++- src/Core/src/Platform/iOS/PickerExtensions.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Core/src/Platform/iOS/MauiPicker.cs b/src/Core/src/Platform/iOS/MauiPicker.cs index aac726ed4419..dbec98a01e1f 100644 --- a/src/Core/src/Platform/iOS/MauiPicker.cs +++ b/src/Core/src/Platform/iOS/MauiPicker.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +#nullable enable +using System.Collections.Generic; using Foundation; using ObjCRuntime; using UIKit; diff --git a/src/Core/src/Platform/iOS/PickerExtensions.cs b/src/Core/src/Platform/iOS/PickerExtensions.cs index 44bc685c27b8..c0283347a53a 100644 --- a/src/Core/src/Platform/iOS/PickerExtensions.cs +++ b/src/Core/src/Platform/iOS/PickerExtensions.cs @@ -1,4 +1,5 @@ -using System; +#nullable enable +using System; using Microsoft.Maui.Handlers; namespace Microsoft.Maui From c8653aeedbb369a5d728fc16bc3e62f16b064577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Su=C3=A1rez=20Ruiz?= Date: Thu, 22 Apr 2021 10:59:22 +0200 Subject: [PATCH 3/6] Fix build error --- src/Core/src/Handlers/Picker/PickerHandler.Windows.cs | 3 +++ src/Core/src/Platform/Windows/MauiCombobox.cs | 3 ++- src/Core/src/Platform/Windows/PickerExtensions.cs | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Core/src/Handlers/Picker/PickerHandler.Windows.cs b/src/Core/src/Handlers/Picker/PickerHandler.Windows.cs index 7c347806537d..ff10eb97ae6a 100644 --- a/src/Core/src/Handlers/Picker/PickerHandler.Windows.cs +++ b/src/Core/src/Handlers/Picker/PickerHandler.Windows.cs @@ -62,6 +62,9 @@ public static void MapTextColor(PickerHandler handler, IPicker picker) handler.NativeView?.UpdateTextColor(picker, handler._defaultForeground); } + [MissingMapper] + public static void MapHorizontalTextAlignment(PickerHandler handler, IPicker view) { } + void OnControlSelectionChanged(object? sender, WSelectionChangedEventArgs e) { if (VirtualView != null && NativeView != null) diff --git a/src/Core/src/Platform/Windows/MauiCombobox.cs b/src/Core/src/Platform/Windows/MauiCombobox.cs index 575afa7967de..6c53648288d2 100644 --- a/src/Core/src/Platform/Windows/MauiCombobox.cs +++ b/src/Core/src/Platform/Windows/MauiCombobox.cs @@ -1,4 +1,5 @@ -using Microsoft.UI.Xaml.Controls; +#nullable enable +using Microsoft.UI.Xaml.Controls; namespace Microsoft.Maui { diff --git a/src/Core/src/Platform/Windows/PickerExtensions.cs b/src/Core/src/Platform/Windows/PickerExtensions.cs index 9201546a87ea..57eaf4e1bf3e 100644 --- a/src/Core/src/Platform/Windows/PickerExtensions.cs +++ b/src/Core/src/Platform/Windows/PickerExtensions.cs @@ -1,4 +1,5 @@ -using Microsoft.Maui.Graphics; +#nullable enable +using Microsoft.Maui.Graphics; using Microsoft.UI.Xaml.Controls; using WBrush = Microsoft.UI.Xaml.Media.Brush; From 53fdcd508281ff26b48b1df06461613c412402c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Su=C3=A1rez=20Ruiz?= Date: Mon, 26 Apr 2021 12:10:12 +0200 Subject: [PATCH 4/6] Register MauiComboBox ResourceDictionary --- src/Core/src/Platform/Windows/MauiWinUIWindow.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Core/src/Platform/Windows/MauiWinUIWindow.cs b/src/Core/src/Platform/Windows/MauiWinUIWindow.cs index a3162aa9b2d3..f5891fb2e639 100644 --- a/src/Core/src/Platform/Windows/MauiWinUIWindow.cs +++ b/src/Core/src/Platform/Windows/MauiWinUIWindow.cs @@ -14,9 +14,17 @@ public MauiWinUIWindow() if (!Application.Current.Resources.ContainsKey("MauiRootContainerStyle")) { - var myResourceDictionary = new Microsoft.UI.Xaml.ResourceDictionary(); - myResourceDictionary.Source = new Uri("ms-appx:///Microsoft.Maui/Platform/Windows/Styles/MauiTextBoxStyle.xbf"); - Microsoft.UI.Xaml.Application.Current.Resources.MergedDictionaries.Add(myResourceDictionary); + var mauiComboBoxDictionary = new ResourceDictionary + { + Source = new Uri("ms-appx:///Microsoft.Maui/Platform/Windows/Styles/MauiComboBoxStyle.xbf") + }; + Application.Current.Resources.MergedDictionaries.Add(mauiComboBoxDictionary); + + var mauiTextBoxDictionary = new ResourceDictionary + { + Source = new Uri("ms-appx:///Microsoft.Maui/Platform/Windows/Styles/MauiTextBoxStyle.xbf") + }; + Application.Current.Resources.MergedDictionaries.Add(mauiTextBoxDictionary); } } From a57fa47c566239e6fe33f12a9fe154abf803f2ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Su=C3=A1rez=20Ruiz?= Date: Tue, 27 Apr 2021 15:58:28 +0200 Subject: [PATCH 5/6] Updated PickerExtensions --- src/Core/src/Platform/Windows/PickerExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/src/Platform/Windows/PickerExtensions.cs b/src/Core/src/Platform/Windows/PickerExtensions.cs index 57eaf4e1bf3e..f15168c380c9 100644 --- a/src/Core/src/Platform/Windows/PickerExtensions.cs +++ b/src/Core/src/Platform/Windows/PickerExtensions.cs @@ -37,7 +37,7 @@ public static void UpdateCharacterSpacing(this MauiComboBox nativeComboBox, IPic nativeComboBox.CharacterSpacing = picker.CharacterSpacing.ToEm(); } - public static void UpdateFont(this ComboBox nativeComboBox, IPicker picker, IFontManager fontManager) => + public static void UpdateFont(this MauiComboBox nativeComboBox, IPicker picker, IFontManager fontManager) => nativeComboBox.UpdateFont(picker.Font, fontManager); } } \ No newline at end of file From 91c58f4aeff7c250b455fb3ef648ec12ae258eca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Su=C3=A1rez=20Ruiz?= Date: Tue, 27 Apr 2021 16:08:18 +0200 Subject: [PATCH 6/6] Updated MauiComboBox --- src/Core/src/Platform/Windows/MauiCombobox.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Core/src/Platform/Windows/MauiCombobox.cs b/src/Core/src/Platform/Windows/MauiCombobox.cs index 6c53648288d2..c6dc801e9a40 100644 --- a/src/Core/src/Platform/Windows/MauiCombobox.cs +++ b/src/Core/src/Platform/Windows/MauiCombobox.cs @@ -9,16 +9,16 @@ public MauiComboBox() { DefaultStyleKey = typeof(MauiComboBox); - DropDownOpened += FormsComboBoxDropDownOpened; - SelectionChanged += FormsComboBoxSelectionChanged; + DropDownOpened += OnMauiComboBoxDropDownOpened; + SelectionChanged += OnMauiComboBoxSelectionChanged; } - void FormsComboBoxDropDownOpened(object? sender, object e) + void OnMauiComboBoxDropDownOpened(object? sender, object e) { MinWidth = ActualWidth; } - void FormsComboBoxSelectionChanged(object? sender, SelectionChangedEventArgs e) + void OnMauiComboBoxSelectionChanged(object? sender, SelectionChangedEventArgs e) { MinWidth = 0; }