ReadOnly Rows and Cells in a DataGrid

A common requirement for a DataGrid control is to have cells, or entire rows and/or columns that are read-only, or in other words non-editable. My requirements for this are as follows:

  1. ReadOnly can be applied to the entire grid, a column, a row, or an individual cell.
  2. The cell(s) must not allow the cell value to be modified.
  3. The cell(s) must be highlighted in some manner (e.g. background colour) to indicate that they are different to the editable cells.
  4. ReadOnly columns require only single direction data-binding (i.e. Mode=OneWay to read-only properties).

GridEditing - ReadOnly Rows

The Microsoft WPF DataGrid meets these requirements via:

  • DataGrid.IsReadOnly property
<toolkit:DataGrid IsReadOnly="True"

  • DataColumn.IsReadOnly property
<toolkit:DataGridTextColumn Binding="{Binding FullName,Mode=OneWay}" IsReadOnly="True"/>

We can use a simple style targeting all DataGridCells to change the background colour.

<Style TargetType="{x:Type toolkit:DataGridCell}">
        <Trigger Property="IsReadOnly" Value="True">
<Setter Property="Background" Value="LightGray"/>

So the only thing that’s really missing here is the ability to mark an entire row as read-only. In my experience this is a common requirement – we have a list of records displayed in the grid some of which are locked/completed/secured, whilst others can be edited.

One solution is to override the OnBeginningEdit method of the DataGrid. The following example assumes that I have an attached property ControlSupport.IsReadOnly.

protected override void OnBeginningEdit( DataGridBeginningEditEventArgs e )
base.OnBeginningEdit( e );
bool isReadOnlyRow = ControlSupport.GetIsReadOnly( e.Row );
if ( isReadOnlyRow )
e.Cancel = true;

However, since I’ve got used to “tweaking” some of the DataGrid code I decided to instead to simply add an IsReadOnly property to the DataGridRow class.

public bool IsReadOnly
get { return (bool) GetValue( IsReadOnlyProperty ); }
set { SetValue( IsReadOnlyProperty, value ); }
// Using a DependencyProperty as the backing store for IsReadOnly.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsReadOnlyProperty =
DependencyProperty.Register( "IsReadOnly", typeof( bool ), typeof( DataGridRow ), 
new FrameworkPropertyMetadata( false, OnNotifyRowAndCellsPropertyChanged ) );

private static void OnNotifyRowAndCellsPropertyChanged( DependencyObject d, 
DependencyPropertyChangedEventArgs e ) { ( d as DataGridRow ).NotifyPropertyChanged( d, e, NotificationTarget.Rows | NotificationTarget.Cells ); }

Then I just needed to make sure that the read-only property DataGridCell.IsReadOnly would correctly return the right value when its row was marked as read-only.

private static object OnCoerceIsReadOnly(DependencyObject d, object baseValue)
var cell = d as DataGridCell;
var column = cell.Column;
var row = cell.RowOwner;
var dataGrid = cell.DataGridOwner;
return DataGridHelper.GetCoercedTransferPropertyValue(

There’s a fairly complex series of notification propagation calls going on within the DataGrid classes. For this solution to work it requires that the DataGridRow.IsReadOnly property changing flows down and causes the read-only DataGridCell.IsReadOnly property to be re-evaulated (via the coerce method above). I had to add another GetCoervedTransferPropertyValue method that took another pair of object/property parameters, and also tweaked the DataGridCell.NotifyPropertyChanged as follows:

else if (e.Property == DataGrid.IsReadOnlyProperty || 
e.Property == DataGridColumn.IsReadOnlyProperty ||
e.Property == DataGridRow.IsReadOnlyProperty ||
e.Property == IsReadOnlyProperty) { DataGridHelper.TransferProperty(this, IsReadOnlyProperty); }

Now in my XAML I can do the following (assuming I have an IsReadOnly property on my business objects):

<Style TargetType="{x:Type toolkit:DataGridRow}">
<Setter Property="IsReadOnly" Value="{Binding IsReadOnly}"/>

15 thoughts on “ReadOnly Rows and Cells in a DataGrid”

  1. Where do I write the code suggested do could you perhaps email mail me a solution of the full cs file?

    This was exactly what I wanted to do.

  2. I’m like Oliver, this is exactly what I would like to do too. Could you please send let me know how to get the source code for this sample?
    Many thanks

  3. Here is a sample solution that demonstrates customising the WPF Toolkit DataGrid – including allowing ReadOnly rows. The solution contains two projects – my sample application and a modified version of the WPFToolkit. It’s based on the March 2009 version of the WPF Toolkit – there aren’t that many changes – you should be able to use BeyondCompare/WifDiff etc. to work out the changes I made.

    Note that to make these changes I modified the original source so you will need to recompile the updated WPF Toolkit. I’m using source control so its easy to track the changes I make and re-apply the “patches” to new versions when Microsoft release them (like the just released June WPF Toolkit). Having said that it would have been nice to achieve the desired fixes by subclassing or using attached properties, events but I think that would have become very “messy” given the number of changes.

    From memory some of the other changes were – removing the ridiculous “Show Calendar” text that displays in the DatePicker, preserving CharacterCasing on grid TextBox… hmm… I can’t remember the rest. Still you should see all the changes by comparing my source against the March 2009 source.

  4. Should the solution work for when I want to hypothetically make the Date of Birth cell readonly for those who’s last name is Smith.

  5. Yes – you simply expose a property on your row’s ViewModel that reflects that rule, e.g. public bool CanModifyDateOfBirth. Then data-bind the new cell IsReadOnly property to that ViewModel property. If the property can change dynamically – e..g when they change the last name, then make sure the CanModifyDateOfBirth setter fires a change notification.

  6. Yes but how is it possible to make only the Date of Birth cell readonly and leave other cells editable?

  7. That’s pretty much the purpose of this post. You could probably hack the specific editing template for that cell – but I choose instead to create an IsReadOnly property at the individual cell level. To do this I had to modify the DataGrid source code itself. Refer comments above.

  8. Hi Nigel, thanks for your great article. I need IsReadOnly property on each individual DataGridCell level. In your article, you changed the original DataGrid code directly, this is okay because you use WPF toolkit. Now, I’m using .NET4 DataGrid, and can’t change the source directly. What can I do?

  9. I have the same problem. I was thinking about some attached property “IsEnabled” solution, but unfortunately I can’t figure it out how to make it works. Any suggestions will be appreciated.

  10. Ok, I think I figure it out: DataGrid class has event “PreparingCellForEdit” and if we subscribe this event and check that current editing cell has attached property “IsReadOnly” set to true we can cancel further edit by calling “CancelEdit()” method on our DataGrid (the reference to that grid we have from casting “object sender” from EventHandler and that EventHandler we are adding to our grid by for example another attached property e.g. “AllowReadOnlyCells”. This works, but I don’t know if this is optimal solution.

  11. I guess there aren’t any follow-ups to this in .NET 4. I found that id I make this class:
    public class DataGridNew : DataGrid
    protected override void OnBeginningEdit(DataGridBeginningEditEventArgs e)
    bool isReadOnlyRow = ControlSupport < --- Here is where it all goes wrong. “ControlSupport” does not exist in the current context. I have been trying to find “ControlSupport” info everywhere to no avail. I’m using C# not VB, what would it be in C#?
    The Bug

  12. Can you pls post yr code in PreparingCellForEdit event on how you did it. I am trying to do similar thing.

  13. ControlSupport is a class with an attached dependency property. You have to create it e.g.:

    namespace YourNamespace
    public class ControlSupport

    public static bool GetIsReadOnly(DependencyObject obj)
    return (bool)obj.GetValue(IsReadOnlyProperty);

    public static void SetIsReadOnly(DependencyObject obj, bool value)
    obj.SetValue(IsReadOnlyProperty, value);

    // Using a DependencyProperty as the backing store for IsReadOnly. This enables animation, styling, binding, etc…
    public static readonly DependencyProperty IsReadOnlyProperty =
    DependencyProperty.RegisterAttached(“IsReadOnly”, typeof(bool), typeof(Control), new PropertyMetadata(false));


Comments are closed.