-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CollectionView with EmptyView and EmptyViewTemplate for Data template selector throws an exception #25418
CollectionView with EmptyView and EmptyViewTemplate for Data template selector throws an exception #25418
Changes from all commits
7d26c90
a8f1b77
9fe14d4
9425483
d7c6eb2
fc95773
bf11ac1
f5e3c66
b2c1a64
a3bfa22
abf8727
da593df
d5a1f5e
086ff49
48e231e
d701ce3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
<?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.EmptyViewGalleries.EmptyViewWithDataTemplateSelector"> | ||
<ContentPage.Resources> | ||
<DataTemplate x:Key="AdvancedTemplate"> | ||
<StackLayout> | ||
<Label Text="No results matched your filter." | ||
Margin="10,25,10,10" | ||
FontAttributes="Bold" | ||
FontSize="18" | ||
HorizontalOptions="Fill" | ||
HorizontalTextAlignment="Center"/> | ||
<Label Text="Try a broader filter?" | ||
FontAttributes="Italic" | ||
FontSize="12" | ||
HorizontalOptions="Fill" | ||
HorizontalTextAlignment="Center"/> | ||
</StackLayout> | ||
</DataTemplate> | ||
|
||
<DataTemplate x:Key="BasicTemplate"> | ||
<Label Text="No items to display." | ||
Margin="10,25,10,10" | ||
FontAttributes="Bold" | ||
FontSize="18" | ||
HorizontalOptions="Fill" | ||
HorizontalTextAlignment="Center"/> | ||
</DataTemplate> | ||
</ContentPage.Resources> | ||
<Grid Margin="20" RowDefinitions="Auto, Auto, *"> | ||
<StackLayout Grid.Row="0"> | ||
<Label Text="1. The test passes if you are able to filter below items by search term." /> | ||
<Label Text="2. The test passes if the filtering 'Xamarin'(no matched results), the string 'No items to display.' will be displayed." /> | ||
<Label Text="3. The test passes if the filtering operation yields no data(except Xamarin), the strings 'No results matched your filter.' and 'Try a broader filter?' will be displayed." /> | ||
</StackLayout> | ||
<SearchBar Grid.Row="1" | ||
x:Name="searchBar" | ||
AutomationId="SearchBar" | ||
SearchCommand="{Binding FilterCommand}" | ||
SearchCommandParameter="{Binding Source={x:Reference searchBar}, Path=Text}" | ||
Placeholder="Filter" /> | ||
<CollectionView Grid.Row="2" | ||
x:Name="collectionView" | ||
AutomationId="Success" | ||
ItemsSource="{Binding Monkeys}" | ||
EmptyView="{Binding Source={x:Reference searchBar}, Path=Text}"> | ||
<CollectionView.ItemTemplate> | ||
<DataTemplate> | ||
<Grid Padding="10"> | ||
<Grid.RowDefinitions> | ||
<RowDefinition Height="Auto" /> | ||
<RowDefinition Height="Auto" /> | ||
</Grid.RowDefinitions> | ||
<Grid.ColumnDefinitions> | ||
<ColumnDefinition Width="Auto" /> | ||
<ColumnDefinition Width="Auto" /> | ||
</Grid.ColumnDefinitions> | ||
<Label Grid.Column="1" | ||
Text="{Binding Name}" | ||
FontAttributes="Bold" /> | ||
<Label Grid.Row="1" | ||
Grid.Column="1" | ||
Text="{Binding Location}" | ||
FontAttributes="Italic" | ||
VerticalOptions="End" /> | ||
</Grid> | ||
</DataTemplate> | ||
</CollectionView.ItemTemplate> | ||
</CollectionView> | ||
</Grid> | ||
</ContentPage> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
#nullable enable | ||
using Microsoft.Maui.Controls; | ||
using Microsoft.Maui.Controls.Xaml; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Collections.ObjectModel; | ||
using System.ComponentModel; | ||
using System.Linq; | ||
using System.Runtime.CompilerServices; | ||
using System.Windows.Input; | ||
|
||
namespace Maui.Controls.Sample.Pages.CollectionViewGalleries.EmptyViewGalleries | ||
{ | ||
[XamlCompilation(XamlCompilationOptions.Compile)] | ||
public partial class EmptyViewWithDataTemplateSelector : ContentPage | ||
{ | ||
public EmptyViewWithDataTemplateSelector() | ||
{ | ||
InitializeComponent(); | ||
var emptyViewTemplateSelector = new SearchTermDataTemplateSelector | ||
{ | ||
DefaultTemplate = (DataTemplate)Resources["AdvancedTemplate"], | ||
OtherTemplate = (DataTemplate)Resources["BasicTemplate"] | ||
}; | ||
collectionView.EmptyViewTemplate = emptyViewTemplateSelector; | ||
BindingContext = new EmptyViewWithDataTemplateSelectorViewModel(); | ||
} | ||
|
||
public class Monkey | ||
{ | ||
public string? Name { get; set; } | ||
public string? Location { get; set; } | ||
public string? Details { get; set; } | ||
} | ||
|
||
public class SearchTermDataTemplateSelector : DataTemplateSelector | ||
{ | ||
public DataTemplate? DefaultTemplate { get; set; } | ||
public DataTemplate? OtherTemplate { get; set; } | ||
|
||
protected override DataTemplate? OnSelectTemplate(object item, BindableObject container) | ||
{ | ||
string query = (string)item; | ||
return query.Equals("xamarin", StringComparison.OrdinalIgnoreCase) ? OtherTemplate : DefaultTemplate; | ||
} | ||
} | ||
|
||
internal class EmptyViewWithDataTemplateSelectorViewModel | ||
{ | ||
public ObservableCollection<Monkey> Monkeys { get; } = new(); | ||
public ICommand FilterCommand => new Command<string>(FilterItems); | ||
|
||
public EmptyViewWithDataTemplateSelectorViewModel() | ||
{ | ||
// Directly populate the ObservableCollection | ||
Monkeys.Add(new Monkey | ||
{ | ||
Name = "Baboon", | ||
Location = "Africa & Asia", | ||
Details = "Baboons are African and Arabian Old World monkeys belonging to the genus Papio, part of the subfamily Cercopithecinae." | ||
}); | ||
} | ||
|
||
private void FilterItems(string filter) | ||
{ | ||
var filteredItems = Monkeys.Where(monkey => monkey.Name?.Contains(filter, StringComparison.OrdinalIgnoreCase) ?? false).ToList(); | ||
Monkeys.Clear(); | ||
foreach (var monkey in filteredItems) | ||
{ | ||
Monkeys.Add(monkey); | ||
} | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
<?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.Issues.Issue25224" | ||
xmlns:local="clr-namespace:Maui.Controls.Sample.Issues" | ||
x:Name="ThisMainPage" | ||
Title="Main Page"> | ||
|
||
<ContentPage.Resources> | ||
<DataTemplate x:Key="AdvancedTemplate"> | ||
<StackLayout> | ||
<Label Text="No results matched your filter." | ||
Margin="10,25,10,10" | ||
FontAttributes="Bold" | ||
FontSize="18" | ||
HorizontalOptions="Fill" | ||
HorizontalTextAlignment="Center"/> | ||
<Label Text="Try a broader filter?" | ||
FontAttributes="Italic" | ||
FontSize="12" | ||
HorizontalOptions="Fill" | ||
HorizontalTextAlignment="Center"/> | ||
</StackLayout> | ||
</DataTemplate> | ||
|
||
<DataTemplate x:Key="BasicTemplate"> | ||
<Label Text="No items to display." | ||
Margin="10,25,10,10" | ||
FontAttributes="Bold" | ||
FontSize="18" | ||
HorizontalOptions="Fill" | ||
HorizontalTextAlignment="Center"/> | ||
</DataTemplate> | ||
</ContentPage.Resources> | ||
<Grid Margin="20" RowDefinitions="Auto, Auto, *"> | ||
<StackLayout Grid.Row="0"> | ||
<Label Text="1. The test passes if you are able to filter below items by search term." /> | ||
<Label Text="2. The test passes if the filtering 'Xamarin'(no matched results), the string 'No items to display.' will be displayed." /> | ||
<Label Text="3. The test passes if the filtering operation yields no data(except Xamarin), the strings 'No results matched your filter.' and 'Try a broader filter?' will be displayed." /> | ||
</StackLayout> | ||
<SearchBar Grid.Row="1" | ||
x:Name="searchBar" | ||
AutomationId="SearchBar" | ||
SearchCommand="{Binding FilterCommand}" | ||
SearchCommandParameter="{Binding Source={x:Reference searchBar}, Path=Text}" | ||
Placeholder="Filter" /> | ||
<CollectionView Grid.Row="2" | ||
x:Name="collectionView" | ||
AutomationId="Success" | ||
ItemsSource="{Binding Monkeys}" | ||
EmptyView="{Binding Source={x:Reference searchBar}, Path=Text}"> | ||
<CollectionView.ItemTemplate> | ||
<DataTemplate> | ||
<Grid Padding="10"> | ||
<Grid.RowDefinitions> | ||
<RowDefinition Height="Auto" /> | ||
<RowDefinition Height="Auto" /> | ||
</Grid.RowDefinitions> | ||
<Grid.ColumnDefinitions> | ||
<ColumnDefinition Width="Auto" /> | ||
<ColumnDefinition Width="Auto" /> | ||
</Grid.ColumnDefinitions> | ||
<Label Grid.Column="1" | ||
Text="{Binding Name}" | ||
FontAttributes="Bold" /> | ||
<Label Grid.Row="1" | ||
Grid.Column="1" | ||
Text="{Binding Location}" | ||
FontAttributes="Italic" | ||
VerticalOptions="End" /> | ||
</Grid> | ||
</DataTemplate> | ||
</CollectionView.ItemTemplate> | ||
</CollectionView> | ||
</Grid> | ||
</ContentPage> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#nullable enable | ||
using System.Collections.ObjectModel; | ||
using System.ComponentModel; | ||
using System.Runtime.CompilerServices; | ||
using System.Windows.Input; | ||
|
||
namespace Maui.Controls.Sample.Issues | ||
{ | ||
[XamlCompilation(XamlCompilationOptions.Compile)] | ||
[Issue(IssueTracker.Github, 25224, "CollectionView - EmptyView with EmptyViewTemplate for Data template selector page throws an exception", PlatformAffected.iOS)] | ||
public partial class Issue25224: ContentPage | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The build is failing:
Could you take a look? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jsuarezruiz , I’ve resolved the build issues mentioned above. Let me know if there’s anything else needed! |
||
{ | ||
public Issue25224() | ||
{ | ||
InitializeComponent(); | ||
var emptyViewTemplateSelector = new SearchTermDataTemplateSelector | ||
{ | ||
DefaultTemplate = (DataTemplate)Resources["AdvancedTemplate"], | ||
OtherTemplate = (DataTemplate)Resources["BasicTemplate"] | ||
}; | ||
collectionView.EmptyViewTemplate = emptyViewTemplateSelector; | ||
BindingContext = new Issue25224ViewModel(); | ||
} | ||
|
||
public class SearchTermDataTemplateSelector : DataTemplateSelector | ||
{ | ||
public DataTemplate? DefaultTemplate { get; set; } | ||
public DataTemplate? OtherTemplate { get; set; } | ||
|
||
protected override DataTemplate? OnSelectTemplate(object item, BindableObject container) | ||
{ | ||
string query = (string)item; | ||
return query.Equals("xamarin", StringComparison.OrdinalIgnoreCase) ? OtherTemplate : DefaultTemplate; | ||
} | ||
} | ||
|
||
internal class Issue25224ViewModel | ||
{ | ||
public ObservableCollection<Monkey> Monkeys { get; } = new(); | ||
public ICommand FilterCommand => new Command<string>(FilterItems); | ||
|
||
public Issue25224ViewModel() | ||
{ | ||
// Directly populate the ObservableCollection | ||
Monkeys.Add(new Monkey | ||
{ | ||
Name = "Baboon", | ||
Location = "Africa & Asia", | ||
Details = "Baboons are African and Arabian Old World monkeys belonging to the genus Papio, part of the subfamily Cercopithecinae." | ||
}); | ||
} | ||
|
||
private void FilterItems(string filter) | ||
{ | ||
var filteredItems = Monkeys.Where(monkey => monkey.Name?.Contains(filter, StringComparison.OrdinalIgnoreCase) ?? false).ToList(); | ||
Monkeys.Clear(); | ||
foreach (var monkey in filteredItems) | ||
{ | ||
Monkeys.Add(monkey); | ||
} | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
using NUnit.Framework; | ||
using UITest.Appium; | ||
using UITest.Core; | ||
|
||
namespace Microsoft.Maui.TestCases.Tests.Issues | ||
{ | ||
internal class Issue25224 : _IssuesUITest | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be nice to include the sample from the test here https://github.com/dotnet/maui/tree/main/src/Controls/samples/Controls.Sample/Pages/Controls/CollectionViewGalleries/EmptyViewGalleries There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jsuarezruiz , |
||
{ | ||
public Issue25224(TestDevice device) : base(device) { } | ||
|
||
public override string Issue => "CollectionView - EmptyView with EmptyViewTemplate for Data template selector page throws an exception"; | ||
|
||
[Test] | ||
[Category(UITestCategories.CollectionView)] | ||
public void CollectionViewEmptyViewDefaultTemplateShouldNotCrashOnDisplay() | ||
{ | ||
App.WaitForElement("SearchBar"); | ||
App.EnterText("SearchBar", "test"); | ||
App.PressEnter(); | ||
// On UI test, pressing Enter twice performs filtering and shows the empty view. | ||
// This code is necessary due to the app's behavior on UI test, which differs from simple samples. | ||
App.PressEnter(); | ||
App.WaitForElement("Success"); | ||
} | ||
|
||
[Test] | ||
[Category(UITestCategories.CollectionView)] | ||
public void CollectionViewEmptyViewOtherTemplateShouldNotCrashOnDisplay() | ||
{ | ||
App.WaitForElement("SearchBar"); | ||
App.EnterText("SearchBar", "xamarin"); | ||
App.PressEnter(); | ||
App.WaitForElement("Success"); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the PR description:
"The exception occurred because the RealizeView method in the ItemsViewController file was attempting to create and render a view when both EmptyView and EmptyViewTemplate were defined in the CollectionView, with a DataTemplateSelector for the EmptyViewTemplate. The original code did not account for the scenario where the viewTemplate was a DataTemplateSelector."
In the case of using a DataTemplateSelector, here
maui/src/Controls/src/Core/Handlers/Items/iOS/TemplateHelpers.cs
Line 34 in bd61427
should select the correct template, and then get the content to create the handler and the PlatformView.
Is the SelectTemplate method returning null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jsuarezruiz ,
In this case, the SelectTemplate method itself isn't returning null. Instead, the exception occurs immediately afterward, when the selected viewTemplate is used in CreateContent. This happens because, on the initial render, there's no template available to select, resulting in viewTemplate being null. This leads to an exception when CreateContent is called with an empty or unassigned DataTemplateSelector.
Let me know if further clarification is needed!