Skip to content

Commit

Permalink
[Windows] Update CollectionView changing ItemsLayout (#14532)
Browse files Browse the repository at this point in the history
* Added sample

* Testing

* Fix the issue

* Small refactoring

* Refactored code

---------

Co-authored-by: Rui Marinho <[email protected]>
  • Loading branch information
jsuarezruiz and rmarinho authored Apr 28, 2023
1 parent e629560 commit d569287
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 100 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Maui.Controls.Sample.Pages.CollectionViewGalleries.AdaptiveCollectionView"
Title="Adaptive CollectionView">
<ContentPage.Content>
<Grid>
<CollectionView
x:Name="CollectionView">
<CollectionView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Item 1</x:String>
<x:String>Item 2</x:String>
<x:String>Item 3</x:String>
<x:String>Item 4</x:String>
<x:String>Item 5</x:String>
<x:String>Item 6</x:String>
<x:String>Item 7</x:String>
<x:String>Item 8</x:String>
</x:Array>
</CollectionView.ItemsSource>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid
HeightRequest="60"
Padding="12">
<Label
HorizontalOptions="Center"
VerticalOptions="Center"
Text="{Binding}"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</ContentPage.Content>
</ContentPage>
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
}
};
Expand Down
40 changes: 31 additions & 9 deletions src/Controls/src/Core/Handlers/Items/ItemsViewHandler.Windows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ public abstract partial class ItemsViewHandler<TItemsView> : ViewHandler<TItemsV
bool _emptyViewDisplayed;
double _previousHorizontalOffset;
double _previousVerticalOffset;
double _previousItemSpacing;
double _previousHorizontalItemSpacing;
double _previousVerticalItemSpacing;

protected ListViewBase ListViewBase => PlatformView;
protected TItemsView ItemsView => VirtualView;
protected TItemsView Element => VirtualView;
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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)
Expand All @@ -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();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
Original file line number Diff line number Diff line change
@@ -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<TItemsView>.~StructuredItemsViewHandler() -> void
override Microsoft.Maui.Controls.Handlers.BoxViewHandler.NeedsContainer.get -> bool
Expand All @@ -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
Expand Down

0 comments on commit d569287

Please sign in to comment.