Мне нужно представить обновляемый список ObservableCollection<RegisterBean> listOfRegisters объектов RegisterBean в виде матрицы с заголовками строк и столбцов. Объект содержит 3 свойства:
byte deviceAddress;
byte register;
byte[] data;
И должно отображаться только одно свойство данные.
Ожидаемый результат как на картинке:

Я достиг этой структуры с обычной сеткой данных, но проблема заключалась в ее обновлении, потому что я использовал конвертер с new DataTable() в качестве возвращаемого значения. Это неверно, потому что он мерцает и повторно отображает все объекты.
Прошил вчера помощи здесь. И это решение работает:
<ItemsControl ItemsSource = "{Binding listOfRegisters}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns = "16"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text = "{Binding Data, Converter = {StaticResource ByteToStringValueConverter}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Но я не понимал, как изменить структуру пользовательского управления и добавить заголовки. Результат решения с itemscontrol:

Спасибо!
UPD: Заголовки должны быть статическими, без сортировки и тому подобного.
Итак, у вас есть в основном работающий DataGrid с незначительной проблемой обновления, и вместо того, чтобы пытаться исправить проблему с обновлением, вы решаете понизить всю свою инфраструктуру до ItemsControl, а затем задаетесь вопросом, как улучшить ItemsControl до такой степени, чтобы вести себя в основном как DataGrid. ?
@ grek40 вы на 100% правы, но я запнулся и подумал, что это способ решить мою проблему. Если есть предложения - милости просим :)
Можете ли вы привести конкретный пример одного объекта RegisterBean с конкретными значениями для deviceAddress, register и data (несколько байтов, пожалуйста) и объяснить, в какой строке / столбце он будет отображаться, что будет отображаться и как это будет редактироваться?
@ grek40 Это представление регистров устройства от 0x00 до 0xFF. Длина может составлять 1 или 2 байта (в зависимости от устройства). Каждая ячейка отображает свойство DataRegisterBean. Например: deviceAddress = 0x60, register 0x5A, data = { 0xFF }. DeviceAddress нужен только для привязки выбранного элемента и использования его позже (я не показываю его в этом конкретном представлении). Значение регистра дает мне положение конкретного bean-компонента в сетке данных (0x5A будет на пересечении строки 0x5 и столбца A). Данные должны отображаться как на картинке в виде значения ячейки.
@AlexEntin Заголовки статичны?
@Babbillumpa да





Просто добавьте вокруг него сетку, например:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height = "Auto"/>
<RowDefinition Height = "Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "Auto"/>
<ColumnDefinition Width = "Auto"/>
</Grid.ColumnDefinitions>
<Grid Grid.Row = "0" Grid.Column = "1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "*"/>
<ColumnDefinition Width = "*"/>
<ColumnDefinition Width = "*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column = "0" Content = "Col 0"/>
<Label Grid.Column = "1" Content = "Col 1"/>
<Label Grid.Column = "2" Content = "Col 2"/>
</Grid>
<Grid Grid.Row = "1" Grid.Column = "0">
<Grid.RowDefinitions>
<RowDefinition Height = "*"/>
<RowDefinition Height = "*"/>
<RowDefinition Height = "*"/>
</Grid.RowDefinitions>
<Label Grid.Row = "0" Content = "Row 0"/>
<Label Grid.Row = "1" Content = "Row 1"/>
<Label Grid.Row = "2" Content = "Row 2"/>
</Grid>
<UniformGrid Rows = "3" Columns = "3" Grid.Column = "1" Grid.Row = "1">
<Button Content = "00"/>
<Button Content = "01"/>
<Button Content = "02"/>
<Button Content = "10"/>
<Button Content = "11"/>
<Button Content = "12"/>
<Button Content = "20"/>
<Button Content = "21"/>
<Button Content = "22"/>
</UniformGrid>
</Grid>
Почему голос против? Это дает хорошие заголовки столбцов и строк вокруг UniformGrid ...?
Я начинаю говорить, что, вероятно, было бы лучше проверить, что не так с DataGrid, и в этом нет необходимости переписывать элементы управления, но если вы все еще хотите использовать ItemsControl ...
Предположим, что в вашей модели ViewModel есть две коллекции (ColHeaders и RowHeaders), которые содержат ваши заголовки, вы можете добавить две другие панели, содержащие заголовки.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "auto"/>
<ColumnDefinition Width = "auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height = "auto"/>
<RowDefinition Height = "auto"/>
</Grid.RowDefinitions>
<!-- Column Headers -->
<ItemsControl Grid.Column = "1" Grid.Row = "0" ItemsSource = "{Binding ColHeaders}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation = "Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock HorizontalAlignment = "Center" VerticalAlignment = "Center" Text = "{Binding}" Width = "30" Height = "30"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl Grid.Row = "1" Grid.Column = "1" ItemsSource = "{Binding listOfRegisters}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns = "16"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text = "{Binding Data, Converter = {StaticResource ByteToStringValueConverter}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- RowHeaders -->
<ItemsControl Grid.Column = "0" Grid.Row = "1" ItemsSource = "{Binding RowHeaders}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock HorizontalAlignment = "Center" VerticalAlignment = "Center" Text = "{Binding}" Width = "30" Height = "30"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
Я также изменил размер текстовых блоков и текстовых полей, чтобы все выровнять.
Я тоже предпочитаю datagrid, может позже попробую найти решение. Спасибо!
ItemsControlне имеет столбцов.GridViewделает (например,ListViewего использует).