Include headers/footers in EmptySource count so they show up when ItemsSource is null (#15979)
* Include headers/footers in EmptySource count so they show up when ItemsSource is null Fixes #8934 * More tests
This commit is contained in:
Родитель
05b741dba5
Коммит
b9f64e153d
|
@ -10,12 +10,12 @@ namespace Microsoft.Maui.Controls.Handlers.Items
|
|||
{
|
||||
public class EmptyViewAdapter : RecyclerView.Adapter
|
||||
{
|
||||
int _headerHeight;
|
||||
double _headerHeight;
|
||||
int _headerViewType;
|
||||
object _headerView;
|
||||
DataTemplate _headerViewTemplate;
|
||||
|
||||
int _footerHeight;
|
||||
double _footerHeight;
|
||||
int _footerViewType;
|
||||
object _footerView;
|
||||
DataTemplate _footerViewTemplate;
|
||||
|
@ -301,18 +301,25 @@ namespace Microsoft.Maui.Controls.Handlers.Items
|
|||
if (item == null)
|
||||
return;
|
||||
|
||||
var sizeRequest = new SizeRequest(new Size(0, 0));
|
||||
var size = Size.Zero;
|
||||
|
||||
if (item is View view)
|
||||
sizeRequest = view.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.IncludeMargins);
|
||||
if (item is IView view)
|
||||
{
|
||||
if (view.Handler == null)
|
||||
{
|
||||
TemplateHelpers.GetHandler(view as View, ItemsView.FindMauiContext());
|
||||
}
|
||||
|
||||
size = view.Measure(double.PositiveInfinity, double.PositiveInfinity);
|
||||
}
|
||||
|
||||
if (item is DataTemplate dataTemplate)
|
||||
{
|
||||
var content = dataTemplate.CreateContent() as View;
|
||||
sizeRequest = content.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.IncludeMargins);
|
||||
var content = dataTemplate.CreateContent() as IView;
|
||||
size = content.Measure(double.PositiveInfinity, double.PositiveInfinity);
|
||||
}
|
||||
|
||||
var itemHeight = (int)sizeRequest.Request.Height;
|
||||
var itemHeight = size.Height;
|
||||
|
||||
if (isHeader)
|
||||
_headerHeight = itemHeight;
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace Microsoft.Maui.Controls.Handlers.Items
|
|||
{
|
||||
sealed internal class EmptySource : IItemsViewSource
|
||||
{
|
||||
public int Count => 0;
|
||||
public int Count => (HasHeader? 1 : 0) + (HasFooter? 1 : 0);
|
||||
|
||||
public bool HasHeader { get; set; }
|
||||
public bool HasFooter { get; set; }
|
||||
|
|
|
@ -50,5 +50,37 @@ namespace Microsoft.Maui.DeviceTests
|
|||
// Without Exceptions here, the test has passed.
|
||||
Assert.Equal(0, (rootPage as IPageContainer<Page>).CurrentPage.Navigation.ModalStack.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NullItemsSourceDisplaysHeaderFooterAndEmptyView()
|
||||
{
|
||||
SetupBuilder();
|
||||
|
||||
var emptyView = new Label { Text = "Empty" };
|
||||
var header = new Label { Text = "Header" };
|
||||
var footer = new Label { Text = "Footer" };
|
||||
|
||||
var collectionView = new CollectionView
|
||||
{
|
||||
ItemsSource = null,
|
||||
EmptyView = emptyView,
|
||||
Header = header,
|
||||
Footer = footer
|
||||
};
|
||||
|
||||
ContentPage contentPage = new ContentPage() { Content = collectionView };
|
||||
|
||||
var frame = collectionView.Frame;
|
||||
|
||||
await CreateHandlerAndAddToWindow<IWindowHandler>(contentPage,
|
||||
async (_) =>
|
||||
{
|
||||
await WaitForUIUpdate(frame, collectionView);
|
||||
|
||||
Assert.True(emptyView.Height > 0, "EmptyView should be laid out");
|
||||
Assert.True(header.Height > 0, "Header should be laid out");
|
||||
Assert.True(footer.Height > 0, "Footer should be laid out");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -170,6 +170,66 @@ namespace Microsoft.Maui.DeviceTests
|
|||
});
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, false, false)]
|
||||
[InlineData(true, false, true)]
|
||||
[InlineData(true, true, false)]
|
||||
[InlineData(true, true, true)]
|
||||
[InlineData(false, false, false)]
|
||||
[InlineData(false, false, true)]
|
||||
[InlineData(false, true, false)]
|
||||
[InlineData(false, true, true)]
|
||||
public async Task CollectionViewStructuralItems(bool hasHeader, bool hasFooter, bool hasData)
|
||||
{
|
||||
SetupBuilder();
|
||||
|
||||
double containerHeight = 500;
|
||||
double containerWidth = 500;
|
||||
var layout = new Grid() { IgnoreSafeArea = true, HeightRequest = containerHeight, WidthRequest = containerWidth };
|
||||
|
||||
Label headerLabel = hasHeader ? new Label { Text = "header" } : null;
|
||||
Label footerLabel = hasFooter ? new Label { Text = "footer" } : null;
|
||||
|
||||
var collectionView = new CollectionView
|
||||
{
|
||||
ItemsLayout = LinearItemsLayout.Vertical,
|
||||
ItemTemplate = new DataTemplate(() => new Label() { HeightRequest = 20, WidthRequest = 20 }),
|
||||
Header = headerLabel,
|
||||
Footer = footerLabel,
|
||||
ItemsSource = hasData ? null : new ObservableCollection<string> { "data" }
|
||||
};
|
||||
|
||||
layout.Add(collectionView);
|
||||
|
||||
var frame = collectionView.Frame;
|
||||
|
||||
await CreateHandlerAndAddToWindow<LayoutHandler>(layout, async handler =>
|
||||
{
|
||||
await WaitForUIUpdate(frame, collectionView);
|
||||
frame = collectionView.Frame;
|
||||
|
||||
#if WINDOWS
|
||||
// On Windows, the ListView pops in and changes the frame, then actually
|
||||
// loads in the data, which updates it again. So we need to wait for the second
|
||||
// update before checking the size
|
||||
await WaitForUIUpdate(frame, collectionView);
|
||||
frame = collectionView.Frame;
|
||||
#endif
|
||||
|
||||
if (hasHeader)
|
||||
{
|
||||
Assert.True(headerLabel.Height > 0);
|
||||
Assert.True(headerLabel.Width > 0);
|
||||
}
|
||||
|
||||
if (hasFooter)
|
||||
{
|
||||
Assert.True(footerLabel.Height > 0);
|
||||
Assert.True(footerLabel.Width > 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> GenerateLayoutOptionsCombos()
|
||||
{
|
||||
var layoutOptions = new LayoutOptions[] { LayoutOptions.Center, LayoutOptions.Start, LayoutOptions.End, LayoutOptions.Fill };
|
||||
|
|
Загрузка…
Ссылка в новой задаче