uno.extensions icon indicating copy to clipboard operation
uno.extensions copied to clipboard

[CSM] Redundant `Grid` in `NonVirtualizingLayout` on WinUI

Open morning4coffe-dev opened this issue 7 months ago • 0 comments

With C# Markup using a NonVirtualizingLayout seems to be wrapping its ItemTemplate content inside a Grid on WinUI. I tried reproducing this issue with Xaml and I can't reproduce the same behavior with similar layout.

C# Markup Details

Create ItemsRepeater that is populated with items of type TextBlock

public MainPage()
{
    this
        .Background(ThemeResource.Get<Brush>("ApplicationPageBackgroundThemeBrush"))
        .Content(new StackPanel()
        .VerticalAlignment(VerticalAlignment.Center)
        .HorizontalAlignment(HorizontalAlignment.Center)
        .Children(
            new TextBlock()
            .HorizontalAlignment(HorizontalAlignment.Center)
            .Text("Hello Uno Platform!"),
            new ItemsRepeater()
            //.Layout(new StackLayout())  // works fine
            .Layout(new MyLayout())       // works fine, using my layout let me to inspect created items
            .HorizontalAlignment(HorizontalAlignment.Center)
            .ItemsSource(Enumerable.Range(0, 5))
            .ItemTemplate<int>(item =>
                new TextBlock()
                .HorizontalAlignment(HorizontalAlignment.Center)
                .Text(() => $"Item {item}"))
        ));
}

This works fine under Desktop and Windows, however in both cases created items differ.

Using my own layout let me to inspect created items:

public class MyLayout : NonVirtualizingLayout
{
    protected override Size MeasureOverride(NonVirtualizingLayoutContext context, Size availableSize)
    {
        double extentHeight = 0.0;
        double extentWidth = 0.0;
        foreach (UIElement element in context.Children)
        {
            element.Measure(availableSize);
            extentHeight += element.DesiredSize.Height;
            extentWidth = Math.Max(extentWidth, element.DesiredSize.Width);
        }

        return new Size(extentWidth, extentHeight);
    }

    protected override Size ArrangeOverride(NonVirtualizingLayoutContext context, Size finalSize)
    {
        double offset = 0.0;
        foreach (FrameworkElement element in context.Children.Cast<FrameworkElement>())
        {
            element.Arrange(new Rect(0, offset, element.DesiredSize.Width, element.DesiredSize.Height));
            offset += element.DesiredSize.Height;

            // inspect the type of element
            Debug.WriteLine($"element type: {element.GetType().Name}");
            Debug.WriteLine($"element.DataContext: {element.DataContext}");
        }

        return finalSize;
    }
}

Surprisingly the type of element differs between Desktop and Windows:

  • Desktop : type is TextBlock as expected
  • Windows: type is Grid. This grid contains one single element of type TextBlock which is the expected one.

The Grid is redundant under Windows, its origin is unknown. I do not use Grid in my code at all.

"Uno.Sdk": "5.4.0-dev.99"

Xaml Details
  <ItemsRepeater ItemsSource="{x:Bind Items}">
    <ItemsRepeater.Layout>
      <local:MyLayout />
    </ItemsRepeater.Layout>
    <ItemsRepeater.ItemTemplate>
      <DataTemplate>
        <TextBlock Text="{Binding Name}" />
      </DataTemplate>
    </ItemsRepeater.ItemTemplate>
  </ItemsRepeater>

repro: UnoNonVirtualizingLayoutWrongItemTypeApp.zip

Originally posted by @kucint in https://github.com/unoplatform/uno.extensions/discussions/2416

morning4coffe-dev avatar Jul 25 '24 09:07 morning4coffe-dev