WPF Grid как ItemsPanel для списка, динамически связанного с элементом ItemsControl

Я использую Grid как ItemsPanel для списка, динамически связанного с ItemsControl. Код ниже работает - с остающейся проблемой: я не могу найти способ динамически инициализировать ColumnDefinitions и RowDefinitions сетки. Как следствие, все значения помещаются друг на друга.

<ItemsControl ItemsSource="{Binding Cells}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Grid.Row" Value="{Binding RowIndex}"/>
            <Setter Property="Grid.Column" Value="{Binding ColumnIndex}"/>
        </Style>
    </ItemsControl.ItemContainerStyle>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Value}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Имейте в виду, что я ищу ответ в соответствии с шаблоном MVVM. Поэтому подкласс и код позади - это обходные пути, но не решения.

Ответ 1

Вам нужно каким-то образом рассказать Grid, сколько строк/столбцов оно имеет. Возможно, при загрузке каждого элемента вы можете проверить значение RowIndex и ColumnIndex и добавить строки/столбцы в сетку, если это необходимо.

В качестве другой альтернативы, возможно, вы можете открыть свойства RowCount и ColumnCount в вашей модели ViewModel, которые вернут max RowIndex и ColumnIndex, а в событии Grid Loaded добавьте, однако, много столбцов/строк, которые вам нужны.

Я считаю вполне приемлемым использовать код в MVVM, если код связан только с пользовательским интерфейсом.

Еще одна идея заключалась бы в том, чтобы упорядочить ваши элементы в коде в 2D-сетке перед возвратом в представление, а затем привязать эту сетку к DataGrid с помощью AutoGenerateColumns=True и удаленные заголовки

Обновление

Моим текущим решением этой проблемы является использование набора AttachedProperties для Grid, который позволяет привязывать свойства RowCount и ColumnCount к свойству в ViewModel

Вы можете найти код моей версии прикрепленных свойств в моем блоге здесь, и их можно использовать следующим образом:

<ItemsPanelTemplate>
    <Grid local:GridHelpers.RowCount="{Binding RowCount}"
          local:GridHelpers.ColumnCount="{Binding ColumnCount}" />
</ItemsPanelTemplate>

Ответ 2

Ваша сетка имеет нулевые строки и столбцы, поэтому все будет отображаться друг над другом. Сделайте что-то вроде ниже, и оно будет работать.

<ItemsControl ItemsSource="{Binding Cells}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
            </Grid>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Grid.Row" Value="{Binding RowIndex}" />
            <Setter Property="Grid.Column" Value="{Binding ColumnIndex}" />
        </Style>
    </ItemsControl.ItemContainerStyle>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Value}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>