From d569287ee81d6e5fd0f89981befd58c25c70da77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Su=C3=A1rez?= Date: Fri, 28 Apr 2023 17:16:45 +0200 Subject: [PATCH] [Windows] Update CollectionView changing ItemsLayout (#14532) * Added sample * Testing * Fix the issue * Small refactoring * Refactored code --------- Co-authored-by: Rui Marinho --- .../AdaptiveCollectionView.xaml | 38 +++++++ .../AdaptiveCollectionView.xaml.cs | 35 ++++++ .../CollectionViewGallery.cs | 1 + .../Items/ItemsViewHandler.Windows.cs | 40 +++++-- .../StructuredItemsViewHandler.Windows.cs | 100 ++---------------- .../Extensions/CollectionViewExtensions.cs | 54 ++++++++++ .../net-windows/PublicAPI.Unshipped.txt | 4 + 7 files changed, 172 insertions(+), 100 deletions(-) create mode 100644 src/Controls/samples/Controls.Sample/Pages/Controls/CollectionViewGalleries/AdaptiveCollectionView.xaml create mode 100644 src/Controls/samples/Controls.Sample/Pages/Controls/CollectionViewGalleries/AdaptiveCollectionView.xaml.cs create mode 100644 src/Controls/src/Core/Platform/Windows/Extensions/CollectionViewExtensions.cs diff --git a/src/Controls/samples/Controls.Sample/Pages/Controls/CollectionViewGalleries/AdaptiveCollectionView.xaml b/src/Controls/samples/Controls.Sample/Pages/Controls/CollectionViewGalleries/AdaptiveCollectionView.xaml new file mode 100644 index 000000000000..0747d62a11d3 --- /dev/null +++ b/src/Controls/samples/Controls.Sample/Pages/Controls/CollectionViewGalleries/AdaptiveCollectionView.xaml @@ -0,0 +1,38 @@ + + + + + + + + Item 1 + Item 2 + Item 3 + Item 4 + Item 5 + Item 6 + Item 7 + Item 8 + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Controls/samples/Controls.Sample/Pages/Controls/CollectionViewGalleries/AdaptiveCollectionView.xaml.cs b/src/Controls/samples/Controls.Sample/Pages/Controls/CollectionViewGalleries/AdaptiveCollectionView.xaml.cs new file mode 100644 index 000000000000..240b4a26ad87 --- /dev/null +++ b/src/Controls/samples/Controls.Sample/Pages/Controls/CollectionViewGalleries/AdaptiveCollectionView.xaml.cs @@ -0,0 +1,35 @@ +using Microsoft.Maui.Controls; +using Microsoft.Maui.Controls.Xaml; + +namespace Maui.Controls.Sample.Pages.CollectionViewGalleries +{ + [XamlCompilation(XamlCompilationOptions.Compile)] + public partial class AdaptiveCollectionView : ContentPage + { + public AdaptiveCollectionView() + { + InitializeComponent(); + } + + protected override void OnAppearing() + { + base.OnAppearing(); + + SizeChanged += OnAdaptiveCollectionViewSizeChanged; + } + + protected override void OnDisappearing() + { + base.OnDisappearing(); + + SizeChanged -= OnAdaptiveCollectionViewSizeChanged; + } + + void OnAdaptiveCollectionViewSizeChanged(object sender, System.EventArgs e) + { + CollectionView.ItemsLayout = Width > 600 + ? new GridItemsLayout(3, ItemsLayoutOrientation.Vertical) + : new LinearItemsLayout(ItemsLayoutOrientation.Vertical); + } + } +} \ No newline at end of file diff --git a/src/Controls/samples/Controls.Sample/Pages/Controls/CollectionViewGalleries/CollectionViewGallery.cs b/src/Controls/samples/Controls.Sample/Pages/Controls/CollectionViewGalleries/CollectionViewGallery.cs index a810a470223a..653a40000150 100644 --- a/src/Controls/samples/Controls.Sample/Pages/Controls/CollectionViewGalleries/CollectionViewGallery.cs +++ b/src/Controls/samples/Controls.Sample/Pages/Controls/CollectionViewGalleries/CollectionViewGallery.cs @@ -51,6 +51,7 @@ public CollectionViewGallery() GalleryBuilder.NavButton("Header/Footer Galleries", () => new HeaderFooterGallery(), Navigation), GalleryBuilder.NavButton("Nested CollectionViews", () => new NestedGalleries.NestedCollectionViewGallery(), Navigation), GalleryBuilder.NavButton("Online images", () => new OnlineImages(), Navigation), + GalleryBuilder.NavButton("Adaptive CollectionView Gallery", () => new AdaptiveCollectionView(), Navigation), } } }; diff --git a/src/Controls/src/Core/Handlers/Items/ItemsViewHandler.Windows.cs b/src/Controls/src/Core/Handlers/Items/ItemsViewHandler.Windows.cs index c0b8a55bd9d1..7118bccf1434 100644 --- a/src/Controls/src/Core/Handlers/Items/ItemsViewHandler.Windows.cs +++ b/src/Controls/src/Core/Handlers/Items/ItemsViewHandler.Windows.cs @@ -32,6 +32,10 @@ public abstract partial class ItemsViewHandler : ViewHandler PlatformView; protected TItemsView ItemsView => VirtualView; protected TItemsView Element => VirtualView; @@ -279,18 +283,36 @@ protected virtual void UpdateEmptyView() protected virtual void UpdateItemsLayout() { - ListViewBase.IsSynchronizedWithCurrentItem = false; + if (ListViewBase is FormsGridView gridView) + { + if (Layout is LinearItemsLayout linearItemsLayout) + { + gridView.Orientation = linearItemsLayout.ToPlatform(); - FindScrollViewer(ListViewBase); + gridView.Span = 1; - _defaultHorizontalScrollVisibility = null; - _defaultVerticalScrollVisibility = null; + if (linearItemsLayout.ItemSpacing != _previousItemSpacing) + { + _previousItemSpacing = linearItemsLayout.ItemSpacing; + gridView.ItemContainerStyle = linearItemsLayout.GetItemContainerStyle(); + } + } - UpdateItemTemplate(); - UpdateItemsSource(); - UpdateVerticalScrollBarVisibility(); - UpdateHorizontalScrollBarVisibility(); - UpdateEmptyView(); + if (Layout is GridItemsLayout gridItemsLayout) + { + gridView.Orientation = gridItemsLayout.ToPlatform(); + + gridView.Span = gridItemsLayout.Span; + + if (gridItemsLayout.HorizontalItemSpacing != _previousHorizontalItemSpacing || + gridItemsLayout.VerticalItemSpacing != _previousVerticalItemSpacing) + { + _previousHorizontalItemSpacing = gridItemsLayout.HorizontalItemSpacing; + _previousVerticalItemSpacing = gridItemsLayout.VerticalItemSpacing; + gridView.ItemContainerStyle = gridItemsLayout.GetItemContainerStyle(); + } + } + } } void FindScrollViewer(ListViewBase listView) diff --git a/src/Controls/src/Core/Handlers/Items/StructuredItemsViewHandler.Windows.cs b/src/Controls/src/Core/Handlers/Items/StructuredItemsViewHandler.Windows.cs index 2e8cc1c4683d..639e023dc61d 100644 --- a/src/Controls/src/Core/Handlers/Items/StructuredItemsViewHandler.Windows.cs +++ b/src/Controls/src/Core/Handlers/Items/StructuredItemsViewHandler.Windows.cs @@ -2,13 +2,7 @@ using System; using System.ComponentModel; using Microsoft.Maui.Controls.Platform; -using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; -using WASDKApp = Microsoft.UI.Xaml.Application; -using WListView = Microsoft.UI.Xaml.Controls.ListView; -using WScrollMode = Microsoft.UI.Xaml.Controls.ScrollMode; -using WSetter = Microsoft.UI.Xaml.Setter; -using WStyle = Microsoft.UI.Xaml.Style; namespace Microsoft.Maui.Controls.Handlers.Items { @@ -87,9 +81,9 @@ protected override ListViewBase SelectListViewBase() case GridItemsLayout gridItemsLayout: return CreateGridView(gridItemsLayout); case LinearItemsLayout listItemsLayout when listItemsLayout.Orientation == ItemsLayoutOrientation.Vertical: - return CreateVerticalListView(listItemsLayout); + return CreateGridView(new GridItemsLayout(ItemsLayoutOrientation.Vertical) { Span = 1 }); case LinearItemsLayout listItemsLayout when listItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal: - return CreateHorizontalListView(listItemsLayout); + return CreateGridView(new GridItemsLayout(ItemsLayoutOrientation.Horizontal) { Span = 1 }); } throw new NotImplementedException("The layout is not implemented"); @@ -202,77 +196,10 @@ static ListViewBase CreateGridView(GridItemsLayout gridItemsLayout) : Orientation.Vertical, Span = gridItemsLayout.Span, - ItemContainerStyle = GetItemContainerStyle(gridItemsLayout) + ItemContainerStyle = gridItemsLayout.GetItemContainerStyle() }; } - static ListViewBase CreateVerticalListView(LinearItemsLayout listItemsLayout) - { - return new FormsListView() - { - ItemContainerStyle = GetVerticalItemContainerStyle(listItemsLayout) - }; - } - - static ListViewBase CreateHorizontalListView(LinearItemsLayout listItemsLayout) - { - var horizontalListView = new FormsListView() - { - ItemsPanel = (ItemsPanelTemplate)WASDKApp.Current.Resources["HorizontalListItemsPanel"], - ItemContainerStyle = GetHorizontalItemContainerStyle(listItemsLayout) - }; - ScrollViewer.SetVerticalScrollBarVisibility(horizontalListView, Microsoft.UI.Xaml.Controls.ScrollBarVisibility.Hidden); - ScrollViewer.SetVerticalScrollMode(horizontalListView, WScrollMode.Disabled); - ScrollViewer.SetHorizontalScrollMode(horizontalListView, WScrollMode.Auto); - ScrollViewer.SetHorizontalScrollBarVisibility(horizontalListView, Microsoft.UI.Xaml.Controls.ScrollBarVisibility.Auto); - - return horizontalListView; - } - - static WStyle GetItemContainerStyle(GridItemsLayout layout) - { - var h = layout?.HorizontalItemSpacing ?? 0; - var v = layout?.VerticalItemSpacing ?? 0; - var margin = WinUIHelpers.CreateThickness(h, v, h, v); - - var style = new WStyle(typeof(GridViewItem)); - - style.Setters.Add(new WSetter(FrameworkElement.MarginProperty, margin)); - style.Setters.Add(new WSetter(Control.PaddingProperty, WinUIHelpers.CreateThickness(0))); - style.Setters.Add(new WSetter(Control.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch)); - - return style; - } - - static WStyle GetVerticalItemContainerStyle(LinearItemsLayout layout) - { - var v = layout?.ItemSpacing ?? 0; - var margin = WinUIHelpers.CreateThickness(0, v, 0, v); - - var style = new WStyle(typeof(ListViewItem)); - - style.Setters.Add(new WSetter(FrameworkElement.MinHeightProperty, 0)); - style.Setters.Add(new WSetter(FrameworkElement.MarginProperty, margin)); - style.Setters.Add(new WSetter(Control.PaddingProperty, WinUIHelpers.CreateThickness(0))); - style.Setters.Add(new WSetter(Control.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch)); - - return style; - } - - static WStyle GetHorizontalItemContainerStyle(LinearItemsLayout layout) - { - var h = layout?.ItemSpacing ?? 0; - var padding = WinUIHelpers.CreateThickness(h, 0, h, 0); - - var style = new WStyle(typeof(ListViewItem)); - - style.Setters.Add(new WSetter(FrameworkElement.MinWidthProperty, 0)); - style.Setters.Add(new WSetter(Control.PaddingProperty, padding)); - style.Setters.Add(new WSetter(Control.VerticalContentAlignmentProperty, VerticalAlignment.Stretch)); - - return style; - } - void UpdateItemsLayoutSpan() { if (ListViewBase is FormsGridView formsGridView) @@ -283,22 +210,13 @@ void UpdateItemsLayoutSpan() void UpdateItemsLayoutItemSpacing() { - if (ListViewBase is FormsGridView formsGridView && Layout is GridItemsLayout gridLayout) - { - formsGridView.ItemContainerStyle = GetItemContainerStyle(gridLayout); - } - - if (Layout is LinearItemsLayout linearItemsLayout) + if (ListViewBase is FormsGridView formsGridView) { - switch (ListViewBase) - { - case FormsListView formsListView: - formsListView.ItemContainerStyle = GetVerticalItemContainerStyle(linearItemsLayout); - break; - case WListView listView: - listView.ItemContainerStyle = GetHorizontalItemContainerStyle(linearItemsLayout); - break; - } + if (Layout is GridItemsLayout gridItemsLayout) + formsGridView.ItemContainerStyle = gridItemsLayout.GetItemContainerStyle(); + + if (Layout is LinearItemsLayout linearItemsLayout) + formsGridView.ItemContainerStyle = linearItemsLayout.GetItemContainerStyle(); } } } diff --git a/src/Controls/src/Core/Platform/Windows/Extensions/CollectionViewExtensions.cs b/src/Controls/src/Core/Platform/Windows/Extensions/CollectionViewExtensions.cs new file mode 100644 index 000000000000..0bf74499f58c --- /dev/null +++ b/src/Controls/src/Core/Platform/Windows/Extensions/CollectionViewExtensions.cs @@ -0,0 +1,54 @@ +#nullable enable +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using WSetter = Microsoft.UI.Xaml.Setter; +using WStyle = Microsoft.UI.Xaml.Style; + +namespace Microsoft.Maui.Controls.Platform +{ + public static class CollectionViewExtensions + { + public static WStyle? GetItemContainerStyle(this LinearItemsLayout? layout) + { + if (layout is null) + return null; + + var h = layout?.ItemSpacing ?? 0; + var v = layout?.ItemSpacing ?? 0; + var margin = WinUIHelpers.CreateThickness(h, v, h, v); + + var style = new WStyle(typeof(GridViewItem)); + + style.Setters.Add(new WSetter(FrameworkElement.MarginProperty, margin)); + style.Setters.Add(new WSetter(Control.PaddingProperty, WinUIHelpers.CreateThickness(0))); + style.Setters.Add(new WSetter(Control.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch)); + + return style; + } + + public static WStyle? GetItemContainerStyle(this GridItemsLayout? layout) + { + if (layout is null) + return null; + + var h = layout?.HorizontalItemSpacing ?? 0; + var v = layout?.VerticalItemSpacing ?? 0; + var margin = WinUIHelpers.CreateThickness(h, v, h, v); + + var style = new WStyle(typeof(GridViewItem)); + + style.Setters.Add(new WSetter(FrameworkElement.MarginProperty, margin)); + style.Setters.Add(new WSetter(Control.PaddingProperty, WinUIHelpers.CreateThickness(0))); + style.Setters.Add(new WSetter(Control.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch)); + + return style; + } + + public static Orientation ToPlatform(this ItemsLayout layout) + { + return layout.Orientation == ItemsLayoutOrientation.Horizontal + ? Orientation.Horizontal + : Orientation.Vertical; + } + } +} diff --git a/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt index c0685d544d13..dd8ad7792b6b 100644 --- a/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt @@ -1,6 +1,7 @@ #nullable enable *REMOVED*override Microsoft.Maui.Controls.RefreshView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size Microsoft.Maui.Controls.Border.~Border() -> void +Microsoft.Maui.Controls.Platform.CollectionViewExtensions Microsoft.Maui.Controls.Platform.ShapesExtensions Microsoft.Maui.Controls.Handlers.Items.StructuredItemsViewHandler.~StructuredItemsViewHandler() -> void override Microsoft.Maui.Controls.Handlers.BoxViewHandler.NeedsContainer.get -> bool @@ -20,6 +21,9 @@ static Microsoft.Maui.Controls.LayoutOptions.operator !=(Microsoft.Maui.Controls static Microsoft.Maui.Controls.LayoutOptions.operator ==(Microsoft.Maui.Controls.LayoutOptions left, Microsoft.Maui.Controls.LayoutOptions right) -> bool static Microsoft.Maui.Controls.Picker.MapHorizontalOptions(Microsoft.Maui.Handlers.IPickerHandler! handler, Microsoft.Maui.Controls.Picker! picker) -> void static Microsoft.Maui.Controls.Picker.MapVerticalOptions(Microsoft.Maui.Handlers.IPickerHandler! handler, Microsoft.Maui.Controls.Picker! picker) -> void +static Microsoft.Maui.Controls.Platform.CollectionViewExtensions.GetItemContainerStyle(this Microsoft.Maui.Controls.GridItemsLayout? layout) -> Microsoft.UI.Xaml.Style? +static Microsoft.Maui.Controls.Platform.CollectionViewExtensions.GetItemContainerStyle(this Microsoft.Maui.Controls.LinearItemsLayout? layout) -> Microsoft.UI.Xaml.Style? +static Microsoft.Maui.Controls.Platform.CollectionViewExtensions.ToPlatform(this Microsoft.Maui.Controls.ItemsLayout! layout) -> Microsoft.UI.Xaml.Controls.Orientation static Microsoft.Maui.Controls.Platform.PickerExtensions.UpdateHorizontalOptions(this Microsoft.UI.Xaml.FrameworkElement! platformView, Microsoft.Maui.Controls.View! view) -> void static Microsoft.Maui.Controls.Platform.PickerExtensions.UpdateVerticalOptions(this Microsoft.UI.Xaml.FrameworkElement! platformView, Microsoft.Maui.Controls.View! view) -> void static Microsoft.Maui.Controls.Platform.ShapesExtensions.UpdatePath(this Microsoft.Maui.Graphics.Win2D.W2DGraphicsView! platformView, Microsoft.Maui.IShapeView! shapeView) -> void