在 DataGrid wpf 中创建自定义编辑行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34988049/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 13:38:34  来源:igfitidea点击:

Create custom edit row in DataGrid wpf

c#wpfdatagrid

提问by Tubc

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.

默认情况下,双击一个单元格会将其转换为编辑模式,当它失去焦点时,如果我们按下 ,它将提交数据或回滚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 Datagridor do I have to implement all the logic myself?

是否已经支持此功能,Datagrid还是我必须自己实现所有逻辑?

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?

我怎样才能防止这种情况?以及如何使“确定”按钮提交所有数据?

回答by AnjumSKhan

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

使用DataGrid.BeginEdit()/ CancelEdit()/ CommitEdit()方法。

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

有一些关于编辑的事件需要处理:BeginningEditCellEditEndingPreparingCellForEdit

Use DataGridCell.IsEditingproperty to turn on/off edit mode.

使用DataGridCell.IsEditing属性打开/关闭编辑模式。

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

你可以得到DataGridRow,从中你可以循环遍历它的DataGridCells。有很多这方面的教程。

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

满足您特定需求的确切方法: 1. 为所有列创建 2 个模板。

  1. And change the CellTemplatewith CellEditingTemplatefor editable column.

  2. And again change CellTemplatewith old CellTemplateafter 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>
    

  1. 并将CellTemplatewith更改CellEditingTemplate为可编辑列。

  2. 取消/提交后再次更改CellTemplate为旧的CellTemplate

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