3

By default, double clicking on a cell turns it into edit mode and when it loses focus it will commit the data or roll back if we press ESC.

I want to create a custom button to switch all cells in a row to edit mode, a button to commit changes and a button to cancel the changes.

Is this feature already supported by the Datagrid or do I have to implement all the logic myself?

I have found a way to switch all cells of a row into edit mode, but every time the textbox loses focus, it turns off edit mode

How can I prevent this? and how can I make the OK button to commit all the data?

1 Answer 1

6

Use DataGrid.BeginEdit()/CancelEdit()/CommitEdit() methods.

There are some events to handle regarding editing : BeginningEdit, CellEditEnding, PreparingCellForEdit.

Use DataGridCell.IsEditing property to turn on/off edit mode.

You can get DataGridRow, from which you can loop through it's DataGridCells. There are plenty of tutorials for this.

Exact approach for your specific needs : 1. Create 2 templates for all columns.

  1. And change the CellTemplate with CellEditingTemplate for editable column.

  2. And again change CellTemplate with old CellTemplate after Cancel/Commit.

    <DataGrid x:Name="DGrid" SelectionUnit="FullRow" AutoGenerateColumns="False" ItemsSource="{Binding Students}" Height="400" CanUserAddRows="False" Margin="10,10,405,18">
    
    <DataGrid.Columns>
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <StackPanel Width="100">
                        <Button Content="Edit" Click="Button_Click_1"/>
                    </StackPanel>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" Width="100">
                        <Button Content="Cancel" Click="Button_Click_2"/>
                        <Button Content="Commit" Click="Button_Click_3"/>
                    </StackPanel>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <TextBox Background="Aquamarine" Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=Explicit}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
        </DataGridTemplateColumn>
    
    </DataGrid.Columns>
    

CodeBehind

        // Edit
        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            DataGridRow row = (DataGridRow)DGrid.ItemContainerGenerator.ContainerFromItem(DGrid.CurrentItem);
            _showCellsEditingTemplate(row);
        }

        // Cancel
        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            DataGridRow row = (DataGridRow)DGrid.ItemContainerGenerator.ContainerFromItem(DGrid.CurrentItem);
            _showCellsNormalTemplate(row);
        }

        // Commit
        private void Button_Click_3(object sender, RoutedEventArgs e)
        {
            DataGridRow row = (DataGridRow)DGrid.ItemContainerGenerator.ContainerFromItem(DGrid.CurrentItem);
            _showCellsNormalTemplate(row, true);
        }

        private void _showCellsEditingTemplate(DataGridRow row)
        {
            foreach (DataGridColumn col in DGrid.Columns)
            {
                DependencyObject parent = VisualTreeHelper.GetParent(col.GetCellContent(row));
                while (parent.GetType().Name != "DataGridCell")
                    parent = VisualTreeHelper.GetParent(parent);

                DataGridCell cell = ((DataGridCell)parent);
                DataGridTemplateColumn c = (DataGridTemplateColumn)col;
                if(c.CellEditingTemplate !=null)
                    cell.Content = ((DataGridTemplateColumn)col).CellEditingTemplate.LoadContent();
            }
        }

        private void _showCellsNormalTemplate(DataGridRow row, bool canCommit = false)
        {
            foreach (DataGridColumn col in DGrid.Columns)
            {
                DependencyObject parent = VisualTreeHelper.GetParent(col.GetCellContent(row));
                while (parent.GetType().Name != "DataGridCell")
                    parent = VisualTreeHelper.GetParent(parent);

                DataGridCell cell = ((DataGridCell)parent);
                DataGridTemplateColumn c = (DataGridTemplateColumn)col;
                if (col.DisplayIndex != 0)
                {
                    if (canCommit == true)
                        ((TextBox)cell.Content).GetBindingExpression(TextBox.TextProperty).UpdateSource();
                    else
                        ((TextBox)cell.Content).GetBindingExpression(TextBox.TextProperty).UpdateTarget();
                }
                cell.Content = c.CellTemplate.LoadContent();                
            }
        }     



public class ViewModel
    {
        ObservableCollection<Student> _students = new ObservableCollection<Student>();
        public ObservableCollection<Student> Students
        { get { return _students; } set { _students = value; } }

        public ViewModel()
        {
            Students.Add(new Student() { Name = "Prashant", Address = "123, N2 B, Barkheda" });
            Students.Add(new Student() { Name = "Amit", Address = "123, N2 B, Piplani" });
            Students.Add(new Student() { Name = "Gopi", Address = "Subhash Nagar" });
            Students.Add(new Student() { Name = "S. Sachin", Address = "HabibGanj" });
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public string Address { get; set; }
    }
Sign up to request clarification or add additional context in comments.

4 Comments

well that's actually what I'm doing to switch all the cells to edit mode. but it keeps switching back if it loses focus, any work around ?
CancelEdit() CommitEdit() return true but the cells still stay as edit mode
@Tubc Plz see my updated exact answer as per your needs.
This is awesome, thank you for solving my problem and increase my knowledge in wpf

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.