.NET MAUI Как сделать правильный Gridlayout в Collectionview с заголовком?

Я пытаюсь создать таблицу в .NET MAUI на основе макета сетки. Это код:

<CollectionView ItemsSource = "{Binding digitalInputs}">
    <CollectionView.Header>
        <Grid ColumnDefinitions = "*,*,*,*">
            <Label Text = "Name" Grid.Column = "0"/>
            <Label Text = "Typ" Grid.Column = "1"/>
            <Label Text = "Status" Grid.Column = "2"/>
            <Label Text = "Aktiv" Grid.Column = "3"/>
        </Grid>
    </CollectionView.Header>
    <CollectionView.ItemTemplate>
        <DataTemplate x:DataType = "services:DigitalInput">
            <Grid ColumnDefinitions = "*,*,*,*">
                <Label Text = "{Binding pName}" Grid.Column = "0"/>
                <Label Text = "{Binding pDigitalType}" Grid.Column = "1"/>
                <Label Text = "{Binding pValueText}" Grid.Column = "2"/>
                <Label Text = "{Binding pActive}" Grid.Column = "3"/>
             </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

Вот результат при работе в режиме отладки на MacCatalyst (Visual Studio для Mac):

Теперь мне интересно, как я могу правильно выровнять сетку заголовка по сетке в шаблоне данных? Есть ли у кого-нибудь предложение о том, как я могу улучшить код, чтобы построить правильную таблицу?

Обновлено: похоже, это ошибка в среде IDE. Когда я изменяю свойство HorizontalOptions в сетке в CollectionView.Header, как было предложено в комментарии, горячая перезагрузка XAML запускает повторную визуализацию представления, и внезапно сетка заголовка правильно выравнивается с сеткой в ​​ItemTemplate.

Я ожидаю, что это сработает. Если вы установите уникальный цвет bg для каждой метки в заголовке, вы можете визуализировать размер каждого из них. Кажется, что контейнер для сетки заголовков больше, чем он есть на самом деле. Возможно, установите для параметров «Горизонтальные» значение «Заполнить» или «Заполнить и развернуть»?

Jason 16.02.2023 17:43

Когда я изменяю свойство при запуске приложения в режиме отладки, XAML HotReload запускает повторную визуализацию представления, и сетка идеально выравнивается.

fonzane 17.02.2023 13:22
Конечные и Readonly классы в PHP
Конечные и Readonly классы в PHP
В прошлом, когда вы не хотели, чтобы другие классы расширяли определенный класс, вы могли пометить его как final.
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
Если вы уже умеете работать с React, создание мобильных приложений для iOS и Android - это новое приключение, в котором вы сможете применить свои...
БЭМ: Конвенция об именовании CSS
БЭМ: Конвенция об именовании CSS
Я часто вижу беспорядочный код CSS, особенно если проект большой. Кроме того, я совершал эту ошибку в профессиональных или личных проектах и...
Революционная веб-разработка ServiceNow
Революционная веб-разработка ServiceNow
В быстро развивающемся мире веб-разработки ServiceNow для достижения успеха крайне важно оставаться на вершине последних тенденций и технологий. По...
Как добавить SEO(Search Engine Optimization) в наше веб-приложение и как это работает?
Как добавить SEO(Search Engine Optimization) в наше веб-приложение и как это работает?
Заголовок веб-страницы играет наиболее важную роль в SEO, он помогает поисковой системе понять, о чем ваш сайт.
Конфигурация Jest в angular
Конфигурация Jest в angular
В этой статье я рассказываю обо всех необходимых шагах, которые нужно выполнить при настройке jest в angular.
1
2
71
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Если вы имеете в виду сначала расположить дочерние элементы по горизонтали, а затем перейти к следующей строке, то текущий MAUI по-прежнему не поддерживает это, вы можете только активировать диапазон (также диапазон не меняется во время выполнения в WinUI прямо сейчас, я думаю, что команда исправить) или создать собственный

    public class HorizontalWrapLayout : StackLayout
{
    public HorizontalWrapLayout()
    {
    }

    protected override ILayoutManager CreateLayoutManager()
    {
        return new HorizontalWrapLayoutManager(this);
    }
}



    public class HorizontalWrapLayoutManager : StackLayoutManager
{
    HorizontalWrapLayout _layout;

    public HorizontalWrapLayoutManager(HorizontalWrapLayout horizontalWrapLayout) : base(horizontalWrapLayout)
    {
        _layout = horizontalWrapLayout;
    }

    public override Size Measure(double widthConstraint, double heightConstraint)
    {
        var padding = _layout.Padding;

        widthConstraint -= padding.HorizontalThickness;

        var rows = new Dictionary<int, List<Size>>();
        var currentRowIndex = 0;
        var currentRow = new List<Size>();

        rows.Add(currentRowIndex, currentRow);

        foreach (var child in _layout)
        {
            if (child.Visibility == Visibility.Collapsed)
            {
                continue;
            }

            var childSize = child.Measure(double.PositiveInfinity, heightConstraint);
            var childWidth = childSize.Width + (currentRow.Any() ? _layout.Spacing : 0);

            var rowWidth = currentRow.Aggregate(0.0, (w, x) => w + x.Width);
            if (rowWidth + childWidth > widthConstraint)
            {
                if (currentRow.Any())
                {
                    currentRowIndex++;
                    currentRow = new List<Size>();
                    rows.Add(currentRowIndex, currentRow);
                }
            }
            else if (currentRow.Any())
            {
                currentRow.Add(new Size(_layout.Spacing, 0));
            }

            currentRow.Add(childSize);
        }

        var totalWidth = 0.0;
        var totalHeight = 0.0;

        if (rows.Any())
        {
            var rowWidths = rows.Select(x => x.Value.Aggregate(0.0, (result, item) => result + item.Width)).ToList();
            var rowHeights = rows.Select(x => x.Value.Any() ? x.Value.Max(i => i.Height) : 0).ToList();

            totalWidth = rowWidths.Any() ? rowWidths.Max() : 0;
            totalHeight = rowHeights.Any() ? rowHeights.Sum() : 0;
            if (rows.Keys.Count > 1)
            {
                totalHeight += _layout.Spacing * (rows.Keys.Count - 1);
            }
        }

        totalWidth += padding.HorizontalThickness;
        totalHeight += padding.VerticalThickness;

        var finalHeight = ResolveConstraints(heightConstraint, Stack.Height, totalHeight, Stack.MinimumHeight, Stack.MaximumHeight);
        var finalWidth = ResolveConstraints(widthConstraint, Stack.Width, totalWidth, Stack.MinimumWidth, Stack.MaximumWidth);

        return new Size(finalWidth, finalHeight);
    }

    public override Size ArrangeChildren(Rect bounds)
    {
        var padding = Stack.Padding;
        double top = padding.Top + bounds.Top;
        double left = padding.Left + bounds.Left;

        double currentRowTop = top;
        double currentX = left;
        double currentRowHeight = 0;

        double maxStackWidth = currentX;

        for (int n = 0; n < _layout.Count; n++)
        {
            var child = _layout[n];

            if (child.Visibility == Visibility.Collapsed)
            {
                continue;
            }

            if (currentX + child.DesiredSize.Width > bounds.Right)
            {
                // Keep track of our maximum width so far
                maxStackWidth = Math.Max(maxStackWidth, currentX);

                // Move down to the next row
                currentX = left;
                currentRowTop += currentRowHeight + _layout.Spacing;
                currentRowHeight = 0;
            }

            var destination = new Rect(currentX, currentRowTop, child.DesiredSize.Width, child.DesiredSize.Height);
            child.Arrange(destination);

            currentX += destination.Width + _layout.Spacing;
            currentRowHeight = Math.Max(currentRowHeight, destination.Height);
        }

        var actual = new Size(maxStackWidth, currentRowTop + currentRowHeight);

        return actual.AdjustForFill(bounds, Stack);
    }

Применение

<app:HorizontalWrapLayout
            BindableLayout.ItemTemplate = "{x:StaticResource HorizontalWrapLayoutItemTemplate}"
            BindableLayout.ItemsSource = "{Binding ControlGroups, Mode=OneWay}"
            HorizontalOptions = "Center"
            Spacing = "50"
            VerticalOptions = "Center" />
Ответ принят как подходящий

Я протестировал предоставленный вами код в iOS, Windows в MAUI. И он может правильно выровнять сетку заголовка по сетке в шаблоне данных в CollectionView. Таким образом, проблема может быть связана с services:DigitalInput получением данных, они должны быть правильно отформатированы без пробелов в этих свойствах.

Ниже приведен пример кода и работающий вывод, надеюсь, он прольет вам свет!

XAML:

<CollectionView ItemsSource = "{Binding digitalInputs}"> 

        <CollectionView.Header>
 
            <Grid ColumnDefinitions = "*,*,*,*">
                <Label Text = "Name" Grid.Column = "0"/>
                <Label Text = "Typ" Grid.Column = "1"/>
                <Label Text = "Status" Grid.Column = "2"/>
                <Label Text = "Aktiv" Grid.Column = "3"/>
            </Grid>
        </CollectionView.Header>

        <CollectionView.ItemTemplate>

            <DataTemplate >

                <Grid ColumnDefinitions = "*,*,*,*">

                    <Label Text = "{Binding pName}" Grid.Column = "0"/>

                    <Label Text = "{Binding pDigitalType}" Grid.Column = "1"/>

                    <Label Text = "{Binding pValueText}" Grid.Column = "2"/>

                    <Label Text = "{Binding pActive}" Grid.Column = "3"/>

                </Grid>

            </DataTemplate>

        </CollectionView.ItemTemplate>

    </CollectionView>

Код программной части:


    public ObservableCollection<Model> digitalInputs { get; set; } 
    public NewPage1()
      {
            InitializeComponent();

            //assign data
            digitalInputs = new ObservableCollection<Model>()
            {

                  new Model{pName = "KipSchalter", pDigitalType = "Zustand",pActive = "OFF", pValueText = "True" },
                  new Model{pName = "KipSchalter", pDigitalType = "Zustand",pActive = "OFF", pValueText = "True" },
                  new Model{pName = "Digital In 3", pDigitalType = "Zustand",pActive = "OFF", pValueText = "FALSE" },
                  new Model{pName = "Digital In 4", pDigitalType = "Zustand",pActive = "OFF", pValueText = "FALSE" }
        }
            ;

            BindingContext = this;
      }

Выход iOS:

Вывод Windows:

Обновлять:

Похоже, это потенциальная проблема в среде IDE. При изменении свойства HorizontalOptions в сетке, как предложил Джейсон, сетка заголовка правильно выравнивается с сеткой в ​​ItemTemplate.

Проблема на самом деле возникает у меня только при работе в режиме отладки MacCatalyst, я должен был это сказать.

fonzane 17.02.2023 13:15

@fonzane Не беспокойтесь, я заметил, что изменение свойства HorizontalOptions сработало. Пожалуйста, помогите принять это как ответ, так как это поможет другим, у кого есть аналогичная проблема. Заранее спасибо!

Alexandar May - MSFT 20.02.2023 06:59

Да, изменение свойства HorizontalOptions, по-видимому, вызывает повторную визуализацию с помощью горячей перезагрузки XAML и исправляет первоначальную ложную визуализацию. У меня больше проблем в этом отношении.

fonzane 20.02.2023 10:06

Другие вопросы по теме