Условно обрабатывать readonly в WPF DataGridCell

У меня есть ситуация, которая должна условно сделать readonly ячейке datagrid wpf. В DataGridCell есть свойство IsReadOnly. Но, к сожалению, это свойство только для чтения! Есть ли способ сделать это?
ant.

Ответ 1

Вы можете использовать DataGrid.BeginningEdit для условной проверки, является ли ячейка доступной для редактирования, а затем установить свойство Отмена на событие args, если нет.

Ответ 2

Аналогичное решение, как Goblin выше, но с небольшим количеством образцов кода:

Идея состоит в том, чтобы динамически переключать CellEditingTemplate между двумя шаблонами, один - тот же, что и в CellTemplate, другой - для редактирования. Это приводит к тому, что режим редактирования действует точно так же, как и нередактирующая ячейка, хотя она находится в режиме редактирования.

Ниже приведен пример кода примера для этого, обратите внимание, что для этого подхода требуется DataGridTemplateColumn:

Сначала определите два шаблона для чтения и редактирования ячеек:

<DataGrid>
  <DataGrid.Resources>
    <!-- the non-editing cell -->
    <DataTemplate x:Key="ReadonlyCellTemplate">
      <TextBlock Text="{Binding MyCellValue}" />
    </DataTemplate>

    <!-- the editing cell -->
    <DataTemplate x:Key="EditableCellTemplate">
      <TextBox Text="{Binding MyCellValue}" />
    </DataTemplate>
  </DataGrid.Resources>
</DataGrid>

Затем определите шаблон данных с дополнительным слоем ContentPresenter и используйте Trigger, чтобы переключить ContentTemplate в ContentPresenter, поэтому приведенные выше два шаблона можно динамически переключать привязкой IsEditable:

<DataGridTemplateColumn CellTemplate="{StaticResource ReadonlyCellTemplate}">
  <DataGridTemplateColumn.CellEditingTemplate>
    <DataTemplate>
      <!-- the additional layer of content presenter -->
      <ContentPresenter x:Name="Presenter" Content="{Binding}" ContentTemplate="{StaticResource ReadonlyCellTemplate}" />
      <DataTemplate.Triggers>
        <!-- dynamically switch the content template by IsEditable binding -->
        <DataTrigger Binding="{Binding IsEditable}" Value="True">
          <Setter TargetName="Presenter" Property="ContentTemplate" Value="{StaticResource EditableCellTemplate}" />
        </DataTrigger>
      </DataTemplate.Triggers>
    </DataTemplate>
  </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

НТН

Ответ 3

Другим очень простым решением этой проблемы является использование стиля DataGridCell

<DataGrid>
    <DataGrid.Resources>
        <Style x:Key="disabledCellStyle" TargetType="DataGridCell">
            <Setter Property="IsEnabled" Value="{Binding IsEnabled}" />
        </Style>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn CellStyle="{StaticResource disabledCellStyle}" />
        <DataGridCheckBoxColumn CellStyle="{StaticResource disabledCellStyle}" />
        <DataGridTextColumn/> /*always enabled*/
    </DataGrid.Columns>
</DataGrid>

Этот стиль предполагает, что в ViewModel есть свойство IsEnabled.

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

Ответ 4

Вы также можете использовать свойство TemplateSelector для установки двух разных DataTemplates (один записываемый и один только для чтения) на основе вашей логики? Просто создайте класс, который наследует от DataTemplateSelector и переопределяет метод SelectTemplate() (здесь у вас есть доступ к datacontext).