0

Question: In a ReadOnly DataGrid, how can we place multiple cells, in a selected row, in Edit mode?

In following ReadOnly DataGrid, the btnEdit_Click event (shown below) successfully places the FirstName column cell of selected row in the edit mode. But I need both FirstName and LastName column cells in the edit mode. If I enclose the entire code of that event in a for loop as for (int i=2; i <=3; i++){...} only the last cell (LastName) column gets the edit mode.

Remark:

  1. All other rows have to stay in ReadOnly mode when user is editing the selected row.
  2. I'm using Entity Framework Core for db operations (e.g. MyDataGrid.ItemsSource = db.Customers.ToList(); etc) and .NET Core 3.1, VS2019 latest version.
  3. No MVVM is involved.
  4. This is a similar post but for a column (not for row).
  5. For brevity, only two columns are shown. Real scenario has more than two columns.

DataGrid:

<DataGrid x:Name="MyDataGrid" IsReadOnly="True" SelectionMode="Single" AutoGenerateColumns="False" Margin="0,25,0,0">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Edit">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Button x:Name="btnEdit" Content="Edit" Click="btnEdit_Click"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Header="ID" Visibility="Collapsed" Binding="{Binding CustomerId}" />
        <DataGridTextColumn Header="FirstName" Binding="{Binding FirstName}" />
        <DataGridTextColumn Header="LastName" Binding="{Binding LastName}" />
    </DataGrid.Columns>
</DataGrid>

Code:

private void btnEdit_Click(object sender, RoutedEventArgs e)
{
    DataGridCell dataGridCell;
    MyDataGrid.CurrentCell = new DataGridCellInfo((sender as Button).DataContext, MyDataGrid.Columns[2]);
    var cellContent = MyDataGrid.CurrentCell.Column.GetCellContent(MyDataGrid.CurrentCell.Item);
    if (cellContent != null)
    {
        dataGridCell = (DataGridCell)cellContent.Parent;
        dataGridCell.IsEditing = true;
    }
}
nam
  • 21,967
  • 37
  • 158
  • 332

1 Answers1

1

You can only place one cell in edit mode at a time no matter the DataGrid's IsReadOnly property is True or False.

If you want to allow users to edit the cells of a specific row after clicking the "Edit" button, you may refer to the below code:

XAML:

<DataGrid x:Name="MyDataGrid" SelectionMode="Single" IsReadOnly="True" AutoGenerateColumns="False" Margin="0,25,0,0"
          SelectedCellsChanged="MyDataGrid_SelectedCellsChanged" SelectionUnit="Cell">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Edit">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Button x:Name="btnEdit" Content="Edit" Click="btnEdit_Click"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Header="ID" Visibility="Collapsed" Binding="{Binding CustomerId}" />
        <DataGridTextColumn Header="FirstName" Binding="{Binding FirstName}" />
        <DataGridTextColumn Header="LastName" Binding="{Binding LastName}" />
    </DataGrid.Columns>
</DataGrid>

Code behind:

    private Customer _editableCustomer;
    private void btnEdit_Click(object sender, RoutedEventArgs e)
    {
        _editableCustomer = (Customer)MyDataGrid.SelectedCells.First().Item;
    }

    private void MyDataGrid_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
    {
        if (e.AddedCells.First().Item == _editableCustomer)
            GetDataGridCell(MyDataGrid.SelectedCells.First()).IsEditing = true;
    }

    public static DataGridCell GetDataGridCell(DataGridCellInfo cellInfo)
    {
        var cellContent = cellInfo.Column.GetCellContent(cellInfo.Item);
        if (cellContent != null)
            return (DataGridCell)cellContent.Parent;

        return null;
    }

However, I personally would not do this. I would set the DataGrid's IsReadOnly property to False and add an event handler for DataGrid's BeginningEdit event. Then I could do whatever I want in the event handler before the user edits the rows.

YantingChen
  • 768
  • 1
  • 12
  • 15
  • I noticed `MyDataGrid_SelectedCellsChanged(...)` event is called before `btnEdit_Click(...)` event. And, at that time since _editableCustomer is null, the `if (e.AddedCells.First().Item == _editableCustomer)` statement in `MyDataGrid_SelectedCellsChanged(...)` is missed - hence no cell is placed in edit mode. – nam May 09 '20 at 15:32
  • Yes. After clicking the edit button, _editableCustomer will be set. It allows users to click and edit the other cells of the same row. – YantingChen May 09 '20 at 16:36
  • In regard to your other suggestion about using `BeginningEdit` event. In this event, how can we make all rows, other than the selected one, `ReadOnly`? My requirement is: All other rows have to stay in ReadOnly mode when user is editing the selected row. – nam May 09 '20 at 16:49