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>