I'm working with a particular table from the backing database which uses a relevant data item as the primary key (in this case, the users' initials). This is something I can't change; it's a legacy design, so I'm stuck with it. But because it's relevant, it has to be shown in the DataGrid I'm working with (bound to the table in the database through an ObjectContext.)
Unfortunately, this means that when a user tries to edit the initials on an existing record, an exception is thrown, because they're trying to edit the entity key of the entity corresponding to this table.
Which is all very well, since they don't need to and indeed shouldn't be editing that column, and so under ordinary circumstances, I'd just mark the column read-only. Trouble is, I do need them to be able to enter new records in the table, but if I mark the column read-only, they can't enter the initials in the "new row". either.
How can I make all the cells in this column read-only except for the one in the "new row"?
(Or is my whole approach here fundamentally misguided - bearing in mind that I can't change the table, and this field needs to exist and be insertable by users, albeit not updateable?)
The above answer from Ron solved half my problem (thanks muchly!), the other half being detecting which cells were part of the "new row" in the first place. That answer, though, came to me with a little experimentation - checking the EntityState of the entity attached to the row will tell you that, since it is "Detached" when you're in the "new row", and changes to "Added" once you've left it, but before changes are actually saved on the ObjectContext (at which time the entity key column can still be edited freely without causing the error).
The code to achieve this, therefore, is as follows:
private void userDataGrid_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
{
if ((string)e.Column.Header == "Initials")
{
// If this is the new row, entity is not yet attached to the context.
if (
(((User)e.Row.Item).EntityState != EntityState.Detached) &&
(((User)e.Row.Item).EntityState != EntityState.Added))
{
e.Cancel = true;
}
}
}