Skip to content

Commit d569287

Browse files
[Windows] Update CollectionView changing ItemsLayout (#14532)
* Added sample * Testing * Fix the issue * Small refactoring * Refactored code --------- Co-authored-by: Rui Marinho <me@ruimarinho.net>
1 parent e629560 commit d569287

7 files changed

Lines changed: 172 additions & 100 deletions

File tree

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ContentPage
3+
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
4+
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
5+
x:Class="Maui.Controls.Sample.Pages.CollectionViewGalleries.AdaptiveCollectionView"
6+
Title="Adaptive CollectionView">
7+
<ContentPage.Content>
8+
<Grid>
9+
<CollectionView
10+
x:Name="CollectionView">
11+
<CollectionView.ItemsSource>
12+
<x:Array Type="{x:Type x:String}">
13+
<x:String>Item 1</x:String>
14+
<x:String>Item 2</x:String>
15+
<x:String>Item 3</x:String>
16+
<x:String>Item 4</x:String>
17+
<x:String>Item 5</x:String>
18+
<x:String>Item 6</x:String>
19+
<x:String>Item 7</x:String>
20+
<x:String>Item 8</x:String>
21+
</x:Array>
22+
</CollectionView.ItemsSource>
23+
<CollectionView.ItemTemplate>
24+
<DataTemplate>
25+
<Grid
26+
HeightRequest="60"
27+
Padding="12">
28+
<Label
29+
HorizontalOptions="Center"
30+
VerticalOptions="Center"
31+
Text="{Binding}"/>
32+
</Grid>
33+
</DataTemplate>
34+
</CollectionView.ItemTemplate>
35+
</CollectionView>
36+
</Grid>
37+
</ContentPage.Content>
38+
</ContentPage>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using Microsoft.Maui.Controls;
2+
using Microsoft.Maui.Controls.Xaml;
3+
4+
namespace Maui.Controls.Sample.Pages.CollectionViewGalleries
5+
{
6+
[XamlCompilation(XamlCompilationOptions.Compile)]
7+
public partial class AdaptiveCollectionView : ContentPage
8+
{
9+
public AdaptiveCollectionView()
10+
{
11+
InitializeComponent();
12+
}
13+
14+
protected override void OnAppearing()
15+
{
16+
base.OnAppearing();
17+
18+
SizeChanged += OnAdaptiveCollectionViewSizeChanged;
19+
}
20+
21+
protected override void OnDisappearing()
22+
{
23+
base.OnDisappearing();
24+
25+
SizeChanged -= OnAdaptiveCollectionViewSizeChanged;
26+
}
27+
28+
void OnAdaptiveCollectionViewSizeChanged(object sender, System.EventArgs e)
29+
{
30+
CollectionView.ItemsLayout = Width > 600
31+
? new GridItemsLayout(3, ItemsLayoutOrientation.Vertical)
32+
: new LinearItemsLayout(ItemsLayoutOrientation.Vertical);
33+
}
34+
}
35+
}

src/Controls/samples/Controls.Sample/Pages/Controls/CollectionViewGalleries/CollectionViewGallery.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public CollectionViewGallery()
5151
GalleryBuilder.NavButton("Header/Footer Galleries", () => new HeaderFooterGallery(), Navigation),
5252
GalleryBuilder.NavButton("Nested CollectionViews", () => new NestedGalleries.NestedCollectionViewGallery(), Navigation),
5353
GalleryBuilder.NavButton("Online images", () => new OnlineImages(), Navigation),
54+
GalleryBuilder.NavButton("Adaptive CollectionView Gallery", () => new AdaptiveCollectionView(), Navigation),
5455
}
5556
}
5657
};

src/Controls/src/Core/Handlers/Items/ItemsViewHandler.Windows.cs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ public abstract partial class ItemsViewHandler<TItemsView> : ViewHandler<TItemsV
3232
bool _emptyViewDisplayed;
3333
double _previousHorizontalOffset;
3434
double _previousVerticalOffset;
35+
double _previousItemSpacing;
36+
double _previousHorizontalItemSpacing;
37+
double _previousVerticalItemSpacing;
38+
3539
protected ListViewBase ListViewBase => PlatformView;
3640
protected TItemsView ItemsView => VirtualView;
3741
protected TItemsView Element => VirtualView;
@@ -279,18 +283,36 @@ protected virtual void UpdateEmptyView()
279283

280284
protected virtual void UpdateItemsLayout()
281285
{
282-
ListViewBase.IsSynchronizedWithCurrentItem = false;
286+
if (ListViewBase is FormsGridView gridView)
287+
{
288+
if (Layout is LinearItemsLayout linearItemsLayout)
289+
{
290+
gridView.Orientation = linearItemsLayout.ToPlatform();
283291

284-
FindScrollViewer(ListViewBase);
292+
gridView.Span = 1;
285293

286-
_defaultHorizontalScrollVisibility = null;
287-
_defaultVerticalScrollVisibility = null;
294+
if (linearItemsLayout.ItemSpacing != _previousItemSpacing)
295+
{
296+
_previousItemSpacing = linearItemsLayout.ItemSpacing;
297+
gridView.ItemContainerStyle = linearItemsLayout.GetItemContainerStyle();
298+
}
299+
}
288300

289-
UpdateItemTemplate();
290-
UpdateItemsSource();
291-
UpdateVerticalScrollBarVisibility();
292-
UpdateHorizontalScrollBarVisibility();
293-
UpdateEmptyView();
301+
if (Layout is GridItemsLayout gridItemsLayout)
302+
{
303+
gridView.Orientation = gridItemsLayout.ToPlatform();
304+
305+
gridView.Span = gridItemsLayout.Span;
306+
307+
if (gridItemsLayout.HorizontalItemSpacing != _previousHorizontalItemSpacing ||
308+
gridItemsLayout.VerticalItemSpacing != _previousVerticalItemSpacing)
309+
{
310+
_previousHorizontalItemSpacing = gridItemsLayout.HorizontalItemSpacing;
311+
_previousVerticalItemSpacing = gridItemsLayout.VerticalItemSpacing;
312+
gridView.ItemContainerStyle = gridItemsLayout.GetItemContainerStyle();
313+
}
314+
}
315+
}
294316
}
295317

296318
void FindScrollViewer(ListViewBase listView)

src/Controls/src/Core/Handlers/Items/StructuredItemsViewHandler.Windows.cs

Lines changed: 9 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@
22
using System;
33
using System.ComponentModel;
44
using Microsoft.Maui.Controls.Platform;
5-
using Microsoft.UI.Xaml;
65
using Microsoft.UI.Xaml.Controls;
7-
using WASDKApp = Microsoft.UI.Xaml.Application;
8-
using WListView = Microsoft.UI.Xaml.Controls.ListView;
9-
using WScrollMode = Microsoft.UI.Xaml.Controls.ScrollMode;
10-
using WSetter = Microsoft.UI.Xaml.Setter;
11-
using WStyle = Microsoft.UI.Xaml.Style;
126

137
namespace Microsoft.Maui.Controls.Handlers.Items
148
{
@@ -87,9 +81,9 @@ protected override ListViewBase SelectListViewBase()
8781
case GridItemsLayout gridItemsLayout:
8882
return CreateGridView(gridItemsLayout);
8983
case LinearItemsLayout listItemsLayout when listItemsLayout.Orientation == ItemsLayoutOrientation.Vertical:
90-
return CreateVerticalListView(listItemsLayout);
84+
return CreateGridView(new GridItemsLayout(ItemsLayoutOrientation.Vertical) { Span = 1 });
9185
case LinearItemsLayout listItemsLayout when listItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal:
92-
return CreateHorizontalListView(listItemsLayout);
86+
return CreateGridView(new GridItemsLayout(ItemsLayoutOrientation.Horizontal) { Span = 1 });
9387
}
9488

9589
throw new NotImplementedException("The layout is not implemented");
@@ -202,77 +196,10 @@ static ListViewBase CreateGridView(GridItemsLayout gridItemsLayout)
202196
: Orientation.Vertical,
203197

204198
Span = gridItemsLayout.Span,
205-
ItemContainerStyle = GetItemContainerStyle(gridItemsLayout)
199+
ItemContainerStyle = gridItemsLayout.GetItemContainerStyle()
206200
};
207201
}
208202

209-
static ListViewBase CreateVerticalListView(LinearItemsLayout listItemsLayout)
210-
{
211-
return new FormsListView()
212-
{
213-
ItemContainerStyle = GetVerticalItemContainerStyle(listItemsLayout)
214-
};
215-
}
216-
217-
static ListViewBase CreateHorizontalListView(LinearItemsLayout listItemsLayout)
218-
{
219-
var horizontalListView = new FormsListView()
220-
{
221-
ItemsPanel = (ItemsPanelTemplate)WASDKApp.Current.Resources["HorizontalListItemsPanel"],
222-
ItemContainerStyle = GetHorizontalItemContainerStyle(listItemsLayout)
223-
};
224-
ScrollViewer.SetVerticalScrollBarVisibility(horizontalListView, Microsoft.UI.Xaml.Controls.ScrollBarVisibility.Hidden);
225-
ScrollViewer.SetVerticalScrollMode(horizontalListView, WScrollMode.Disabled);
226-
ScrollViewer.SetHorizontalScrollMode(horizontalListView, WScrollMode.Auto);
227-
ScrollViewer.SetHorizontalScrollBarVisibility(horizontalListView, Microsoft.UI.Xaml.Controls.ScrollBarVisibility.Auto);
228-
229-
return horizontalListView;
230-
}
231-
232-
static WStyle GetItemContainerStyle(GridItemsLayout layout)
233-
{
234-
var h = layout?.HorizontalItemSpacing ?? 0;
235-
var v = layout?.VerticalItemSpacing ?? 0;
236-
var margin = WinUIHelpers.CreateThickness(h, v, h, v);
237-
238-
var style = new WStyle(typeof(GridViewItem));
239-
240-
style.Setters.Add(new WSetter(FrameworkElement.MarginProperty, margin));
241-
style.Setters.Add(new WSetter(Control.PaddingProperty, WinUIHelpers.CreateThickness(0)));
242-
style.Setters.Add(new WSetter(Control.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch));
243-
244-
return style;
245-
}
246-
247-
static WStyle GetVerticalItemContainerStyle(LinearItemsLayout layout)
248-
{
249-
var v = layout?.ItemSpacing ?? 0;
250-
var margin = WinUIHelpers.CreateThickness(0, v, 0, v);
251-
252-
var style = new WStyle(typeof(ListViewItem));
253-
254-
style.Setters.Add(new WSetter(FrameworkElement.MinHeightProperty, 0));
255-
style.Setters.Add(new WSetter(FrameworkElement.MarginProperty, margin));
256-
style.Setters.Add(new WSetter(Control.PaddingProperty, WinUIHelpers.CreateThickness(0)));
257-
style.Setters.Add(new WSetter(Control.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch));
258-
259-
return style;
260-
}
261-
262-
static WStyle GetHorizontalItemContainerStyle(LinearItemsLayout layout)
263-
{
264-
var h = layout?.ItemSpacing ?? 0;
265-
var padding = WinUIHelpers.CreateThickness(h, 0, h, 0);
266-
267-
var style = new WStyle(typeof(ListViewItem));
268-
269-
style.Setters.Add(new WSetter(FrameworkElement.MinWidthProperty, 0));
270-
style.Setters.Add(new WSetter(Control.PaddingProperty, padding));
271-
style.Setters.Add(new WSetter(Control.VerticalContentAlignmentProperty, VerticalAlignment.Stretch));
272-
273-
return style;
274-
}
275-
276203
void UpdateItemsLayoutSpan()
277204
{
278205
if (ListViewBase is FormsGridView formsGridView)
@@ -283,22 +210,13 @@ void UpdateItemsLayoutSpan()
283210

284211
void UpdateItemsLayoutItemSpacing()
285212
{
286-
if (ListViewBase is FormsGridView formsGridView && Layout is GridItemsLayout gridLayout)
287-
{
288-
formsGridView.ItemContainerStyle = GetItemContainerStyle(gridLayout);
289-
}
290-
291-
if (Layout is LinearItemsLayout linearItemsLayout)
213+
if (ListViewBase is FormsGridView formsGridView)
292214
{
293-
switch (ListViewBase)
294-
{
295-
case FormsListView formsListView:
296-
formsListView.ItemContainerStyle = GetVerticalItemContainerStyle(linearItemsLayout);
297-
break;
298-
case WListView listView:
299-
listView.ItemContainerStyle = GetHorizontalItemContainerStyle(linearItemsLayout);
300-
break;
301-
}
215+
if (Layout is GridItemsLayout gridItemsLayout)
216+
formsGridView.ItemContainerStyle = gridItemsLayout.GetItemContainerStyle();
217+
218+
if (Layout is LinearItemsLayout linearItemsLayout)
219+
formsGridView.ItemContainerStyle = linearItemsLayout.GetItemContainerStyle();
302220
}
303221
}
304222
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#nullable enable
2+
using Microsoft.UI.Xaml;
3+
using Microsoft.UI.Xaml.Controls;
4+
using WSetter = Microsoft.UI.Xaml.Setter;
5+
using WStyle = Microsoft.UI.Xaml.Style;
6+
7+
namespace Microsoft.Maui.Controls.Platform
8+
{
9+
public static class CollectionViewExtensions
10+
{
11+
public static WStyle? GetItemContainerStyle(this LinearItemsLayout? layout)
12+
{
13+
if (layout is null)
14+
return null;
15+
16+
var h = layout?.ItemSpacing ?? 0;
17+
var v = layout?.ItemSpacing ?? 0;
18+
var margin = WinUIHelpers.CreateThickness(h, v, h, v);
19+
20+
var style = new WStyle(typeof(GridViewItem));
21+
22+
style.Setters.Add(new WSetter(FrameworkElement.MarginProperty, margin));
23+
style.Setters.Add(new WSetter(Control.PaddingProperty, WinUIHelpers.CreateThickness(0)));
24+
style.Setters.Add(new WSetter(Control.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch));
25+
26+
return style;
27+
}
28+
29+
public static WStyle? GetItemContainerStyle(this GridItemsLayout? layout)
30+
{
31+
if (layout is null)
32+
return null;
33+
34+
var h = layout?.HorizontalItemSpacing ?? 0;
35+
var v = layout?.VerticalItemSpacing ?? 0;
36+
var margin = WinUIHelpers.CreateThickness(h, v, h, v);
37+
38+
var style = new WStyle(typeof(GridViewItem));
39+
40+
style.Setters.Add(new WSetter(FrameworkElement.MarginProperty, margin));
41+
style.Setters.Add(new WSetter(Control.PaddingProperty, WinUIHelpers.CreateThickness(0)));
42+
style.Setters.Add(new WSetter(Control.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch));
43+
44+
return style;
45+
}
46+
47+
public static Orientation ToPlatform(this ItemsLayout layout)
48+
{
49+
return layout.Orientation == ItemsLayoutOrientation.Horizontal
50+
? Orientation.Horizontal
51+
: Orientation.Vertical;
52+
}
53+
}
54+
}

src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#nullable enable
22
*REMOVED*override Microsoft.Maui.Controls.RefreshView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
33
Microsoft.Maui.Controls.Border.~Border() -> void
4+
Microsoft.Maui.Controls.Platform.CollectionViewExtensions
45
Microsoft.Maui.Controls.Platform.ShapesExtensions
56
Microsoft.Maui.Controls.Handlers.Items.StructuredItemsViewHandler<TItemsView>.~StructuredItemsViewHandler() -> void
67
override Microsoft.Maui.Controls.Handlers.BoxViewHandler.NeedsContainer.get -> bool
@@ -20,6 +21,9 @@ static Microsoft.Maui.Controls.LayoutOptions.operator !=(Microsoft.Maui.Controls
2021
static Microsoft.Maui.Controls.LayoutOptions.operator ==(Microsoft.Maui.Controls.LayoutOptions left, Microsoft.Maui.Controls.LayoutOptions right) -> bool
2122
static Microsoft.Maui.Controls.Picker.MapHorizontalOptions(Microsoft.Maui.Handlers.IPickerHandler! handler, Microsoft.Maui.Controls.Picker! picker) -> void
2223
static Microsoft.Maui.Controls.Picker.MapVerticalOptions(Microsoft.Maui.Handlers.IPickerHandler! handler, Microsoft.Maui.Controls.Picker! picker) -> void
24+
static Microsoft.Maui.Controls.Platform.CollectionViewExtensions.GetItemContainerStyle(this Microsoft.Maui.Controls.GridItemsLayout? layout) -> Microsoft.UI.Xaml.Style?
25+
static Microsoft.Maui.Controls.Platform.CollectionViewExtensions.GetItemContainerStyle(this Microsoft.Maui.Controls.LinearItemsLayout? layout) -> Microsoft.UI.Xaml.Style?
26+
static Microsoft.Maui.Controls.Platform.CollectionViewExtensions.ToPlatform(this Microsoft.Maui.Controls.ItemsLayout! layout) -> Microsoft.UI.Xaml.Controls.Orientation
2327
static Microsoft.Maui.Controls.Platform.PickerExtensions.UpdateHorizontalOptions(this Microsoft.UI.Xaml.FrameworkElement! platformView, Microsoft.Maui.Controls.View! view) -> void
2428
static Microsoft.Maui.Controls.Platform.PickerExtensions.UpdateVerticalOptions(this Microsoft.UI.Xaml.FrameworkElement! platformView, Microsoft.Maui.Controls.View! view) -> void
2529
static Microsoft.Maui.Controls.Platform.ShapesExtensions.UpdatePath(this Microsoft.Maui.Graphics.Win2D.W2DGraphicsView! platformView, Microsoft.Maui.IShapeView! shapeView) -> void

0 commit comments

Comments
 (0)