wpfreadonlydatagridcell

How to make WPF DataGridCell ReadOnly?


I understand you can make the whole DataGrid or a whole column readyonly (IsReadOnly = true). However, at cell level this property is ready only. But I do need this level of granularity. There is blog about adding IsReadOnly to a row by changing the source code in old days when DataGrid was public domain, but now I don't have source code for DataGrid. What's workaround?

Making cell disabled (IsEnabled=false) almost meets my need. But the problem is that you can't even click the disabled cell to select the row (I have full row selection mode).

EDIT: Since nobody has responded to this question, so I guess it's not an easy fix. Here is a possible workaround: Make the cell uneditable. The only problem is that clicking the cell doesn't select the row. I just noticed that MouseDown or MouseUp event of the DataGrid is still fired when the disabled cell is clicked. In this event handler, if I could figure out the row it clicked, I could select the row programmatically. However, I couldn't figure out how to find the underlying row from DataGrid.InputHitTest. Can somebody please give me some tip?


Solution

  • I've encountered the same problem, the cell should be read-only in some rows but not in the others. Here is a workaround solution:

    The idea is to dynamically switch the CellEditingTemplate between two templates, one is the same as the one in the CellTemplate, the other is for editing. This makes the edit mode acts exactly the same as the non-editing cell although it is in edit mode.

    The following is some sample code for doing this, notice that this approach requires DataGridTemplateColumn:

    First, define two templates for read-only and editing cells:

    <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>
    

    Then define a data template with additional ContentPresenter layer and use Trigger to switch the ContentTemplate of the ContentPresenter, so the above two templates can be switched dynamically by the IsEditable binding:

    <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>
    

    HTH