Skip to content

Commit

Permalink
Fixed CollectionViewHandler2 null reference exception if ItemsLayout …
Browse files Browse the repository at this point in the history
…is set for Tablet but not on mobile devices (#26152)

* Fixed CollectionViewHandler2 null reference exception

* Removed unnecessary code changes

* Modified code changes and added test case images
  • Loading branch information
NirmalKumarYuvaraj authored Dec 4, 2024
1 parent a57ab5d commit 0ddc794
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 16 deletions.
42 changes: 26 additions & 16 deletions src/Controls/src/Core/Handlers/Items2/CollectionViewHandler2.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,21 +155,8 @@ protected override UICollectionViewLayout SelectLayout()

var itemSizingStrategy = ItemsView.ItemSizingStrategy;
var itemsLayout = ItemsView.ItemsLayout;

//TODO: Find a better way to do this
itemsLayout.PropertyChanged += (sender, args) =>
{
if (args.PropertyName == nameof(ItemsLayout.SnapPointsAlignment) ||
args.PropertyName == nameof(ItemsLayout.SnapPointsType) ||
args.PropertyName == nameof(GridItemsLayout.VerticalItemSpacing) ||
args.PropertyName == nameof(GridItemsLayout.HorizontalItemSpacing) ||
args.PropertyName == nameof(GridItemsLayout.Span) ||
args.PropertyName == nameof(LinearItemsLayout.ItemSpacing))

{
UpdateLayout();
}
};

SubscribeToItemsLayoutPropertyChanged(itemsLayout);

if (itemsLayout is GridItemsLayout gridItemsLayout)
{
Expand All @@ -182,7 +169,10 @@ protected override UICollectionViewLayout SelectLayout()
}

// Fall back to vertical list
return LayoutFactory2.CreateList(new LinearItemsLayout(ItemsLayoutOrientation.Vertical), groupInfo, headerFooterInfo);
var fallbackItemsLayout = new LinearItemsLayout(ItemsLayoutOrientation.Vertical);
// Manually setting the value to ensure the property changed event is properly wired..
ItemsView.ItemsLayout = fallbackItemsLayout;
return LayoutFactory2.CreateList(fallbackItemsLayout, groupInfo, headerFooterInfo);
}

public static void MapHeaderTemplate(CollectionViewHandler2 handler, StructuredItemsView itemsView)
Expand All @@ -206,5 +196,25 @@ public static void MapItemSizingStrategy(CollectionViewHandler2 handler, Structu
{
handler.UpdateLayout();
}

void SubscribeToItemsLayoutPropertyChanged(IItemsLayout itemsLayout)
{
if(itemsLayout is not null)
{
itemsLayout.PropertyChanged += (sender, args) =>
{
if (args.PropertyName == nameof(ItemsLayout.SnapPointsAlignment) ||
args.PropertyName == nameof(ItemsLayout.SnapPointsType) ||
args.PropertyName == nameof(GridItemsLayout.VerticalItemSpacing) ||
args.PropertyName == nameof(GridItemsLayout.HorizontalItemSpacing) ||
args.PropertyName == nameof(GridItemsLayout.Span) ||
args.PropertyName == nameof(LinearItemsLayout.ItemSpacing))

{
UpdateLayout();
}
};
}
}
}
}
33 changes: 33 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue26065.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?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"
xmlns:local="clr-namespace:Maui.Controls.Sample"
x:Class="Maui.Controls.Sample.Issues.Issue26065">

<Grid RowDefinitions="Auto,*">
<Button AutomationId="ToggleButton" x:Name="btn" Clicked="Button_Clicked" Text="Modify Itemspacing" Grid.Row="0"/>
<local:CollectionView2 x:Name="collView" AutomationId="CollectionView"
ItemsLayout="{OnIdiom Tablet='VerticalGrid, 2'}"
Grid.Row="1"
ItemsSource="{Binding Books}"
VerticalOptions="Fill">

<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10"
Background="White">
<VerticalStackLayout>
<Label Text="{Binding Title}"
FontSize="16"
FontAttributes="Bold"/>
<Label Text="{Binding Author}"
FontSize="14"
TextColor="Gray"/>
</VerticalStackLayout>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</local:CollectionView2>
</Grid>

</ContentPage>
68 changes: 68 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue26065.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using System.Collections.ObjectModel;

namespace Maui.Controls.Sample.Issues
{
[Issue(IssueTracker.Github, 26065, "CollectionViewHandler2 null reference exception if ItemsLayout is set for Tablet but NOT Phone", PlatformAffected.iOS)]
public partial class Issue26065 : ContentPage
{
public Issue26065()
{
InitializeComponent();BindingContext = new BookViewModel();
}


private void Button_Clicked(object sender, EventArgs e)
{
if(collView.ItemsLayout is LinearItemsLayout linearItemsLayout)
{
linearItemsLayout.ItemSpacing = 20;
}
}
}

public class Book
{
public string Title { get; set; }
public string Author { get; set; }
}

// ViewModel
public class BookViewModel
{
private ObservableCollection<Book> _bookGroups;
public ObservableCollection<Book> Books
{
get => _bookGroups;
set
{
_bookGroups = value;

}
}

public BookViewModel()
{
LoadBooks();
}

private void LoadBooks()
{
Books = new ObservableCollection<Book>
{

new Book { Title = "Dune", Author = "Frank Herbert" },
new Book { Title = "Neuromancer", Author = "William Gibson" },


new Book { Title = "The Hobbit", Author = "J.R.R. Tolkien" },
new Book { Title = "Name of the Wind", Author = "Patrick Rothfuss" },


new Book { Title = "Murder on the Orient Express", Author = "Agatha Christie" },
new Book { Title = "The Girl with the Dragon Tattoo", Author = "Stieg Larsson" }

};
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#if IOS // Issue occurs only in CollectionViewHandler2

using NUnit.Framework;
using UITest.Appium;
using UITest.Core;
namespace Microsoft.Maui.TestCases.Tests.Issues
{
public class Issue26065 : _IssuesUITest
{
public Issue26065(TestDevice device) : base(device) { }

public override string Issue => "CollectionViewHandler2 null reference exception if ItemsLayout is set for Tablet but NOT Phone";

[Test]
[Category(UITestCategories.CollectionView)]
public void CollectionViewShouldUseFallBackItemsLayout()
{
App.WaitForElement("CollectionView");
}

[Test]
[Category(UITestCategories.CollectionView)]
public void CollectionViewWithFallbackVauleShouldUpdateAtRunTime()
{
App.WaitForElement("ToggleButton");
App.Tap("ToggleButton");
VerifyScreenshot();
}

}
}
#endif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 0ddc794

Please sign in to comment.