Пользовательский класс ячейки в сетке данных - PullRequest
0 голосов
/ 14 ноября 2018

Я создал матричный элемент управления, производный от DataGrid, который должен отображать сложные типы в ячейках. Эти сложные типы должны затем быть стилизованы шаблоном.

При использовании AutoGenerateColumns DataGrid автоматически создает столбцы и типы ячеек на основе типа списка, назначенного для ItemsSource.

Я хочу заменить строку, столбец и тип ячейки сетки для выполнения пользовательских операций и привязок с привязкой к ней модели представления. Я уже смог создать пользовательские строку и столбец. Есть ли способ получить из DataGridCell и заставить сетку данных использовать этот тип вместо типа по умолчанию?

Я посмотрел исходный код .net и увидел, что в строке используется DataGridCellsPresenter для создания ячеек, но это свойство недоступно.

public class MatrixControl : DataGrid
{
  public static readonly DependencyProperty COLUMN_HEADER_TEMPLATE_PROPERTY = DependencyProperty.Register(nameof(ColumnHeaderTemplate), typeof(DataTemplate), typeof(MatrixControl), new PropertyMetadata(default(object)));

  public DataTemplate ColumnHeaderTemplate { get { return (DataTemplate)GetValue(COLUMN_HEADER_TEMPLATE_PROPERTY); } set { SetValue(COLUMN_HEADER_TEMPLATE_PROPERTY, value); } }

  private MatrixViewModel ViewModel { get { return DataContext as MatrixViewModel; } }

  public MatrixControl()
  {
    DataContextChanged += OnDataContextChanged;
    SelectionMode = DataGridSelectionMode.Extended;
    SelectionUnit = DataGridSelectionUnit.CellOrRowHeader;
    AutoGenerateColumns = true;
  }

  private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
  {
    ItemsSource = ViewModel.Rows.Select(c => new Row(c, ViewModel));
  }

  protected override void OnAutoGeneratingColumn(DataGridAutoGeneratingColumnEventArgs e)
  {
    e.Cancel = true;
    Columns.Clear();
    foreach (var column in ViewModel.Columns)
    {
      Columns.Add(new MatrixColumn(column)
      {
        HeaderTemplate = ColumnHeaderTemplate
      });
    }
  }
}

class MatrixColumn : DataGridTemplateColumn
{
  public object Value { get; }

  public MatrixColumn(object value)
  {
    Value = value;
  }
}

class Row
{
  public object Value { get; }

  public Row(object value)
  {
    Value = value;
  }
}

class MatrixViewModel
{
  public IEnumerable<object> Columns { get; set; }
  public IEnumerable<object> Rows { get; set; }
}

Обновление: попытка заменить DataGridCellsPresenter

// in data grid class
protected override DependencyObject GetContainerForItemOverride()
{
  return new MatrixRow();
}

class MatrixRow : DataGridRow
{       
  public MatrixRow()
  {
    var cellPresenterProperty = GetType().GetProperty("CellsPresenter", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty);
    cellPresenterProperty.SetValue(this, new MatrixCellPresenter());
  }
}

class MatrixCellPresenter : DataGridCellsPresenter
{
  protected override DependencyObject GetContainerForItemOverride()
  {
    // won't get called, the presenter is overriden by the internal one
    return new MatrixCell();
  }
}

1 Ответ

0 голосов
/ 15 ноября 2018

Я нашел решение моей проблемы с этой публикацией .

Код вопроса пока хорош, единственное, что нужно было сделать, это переписать шаблон MatrixRow в xaml. Ради полноты я выкладываю код xaml из другого вопроса:

<Style TargetType="{x:Type local:MatrixRow}">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type local:MatrixRow}">
        <Border x:Name="DGR_Border"
                      BorderBrush="{TemplateBinding BorderBrush}"
                      BorderThickness="{TemplateBinding BorderThickness}"
                      SnapsToDevicePixels="True">
          <SelectiveScrollingGrid>
            <SelectiveScrollingGrid.ColumnDefinitions>
              <ColumnDefinition Width="Auto" />
              <ColumnDefinition Width="*" />
            </SelectiveScrollingGrid.ColumnDefinitions>
            <SelectiveScrollingGrid.RowDefinitions>
              <RowDefinition Height="*" />
              <RowDefinition Height="Auto" />
            </SelectiveScrollingGrid.RowDefinitions>

            <!-- Make sure to register your custom DataGridCellsPresenter here as following -->

            <local:MatrixCellPresenter Grid.Column="1"
                              ItemsPanel="{TemplateBinding ItemsPanel}"
                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
            <DataGridDetailsPresenter Grid.Column="1"
                                Grid.Row="1"
                                Visibility="{TemplateBinding DetailsVisibility}"
                                SelectiveScrollingGrid.SelectiveScrollingOrientation=
                                  "{Binding AreRowDetailsFrozen, 
                                  ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical},
                                  Converter={x:Static DataGrid.RowDetailsScrollingConverter}, 
                                  RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
            <DataGridRowHeader Grid.RowSpan="2"
                             SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
                             Visibility="{Binding HeadersVisibility, 
                              ConverterParameter={x:Static DataGridHeadersVisibility.Row}, 
                              Converter={x:Static DataGrid.HeadersVisibilityConverter}, 
                              RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
          </SelectiveScrollingGrid>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...