在WPF中创建自定义编辑行的DataGrid

3

默认情况下,双击单元格会将其转换为编辑模式,当它失去焦点时,如果我们按下 ESC,它将提交数据或回滚更改。

我想创建一个自定义按钮来切换一整行所有单元格进入编辑模式,一个用于提交更改的按钮和一个用于取消更改的按钮。

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

我已经找到了一种将一整行所有单元格切换到编辑模式的方法,但每次文本框失去焦点时,都会关闭编辑模式。

我该如何防止这种情况发生?并且如何使 "确定" 按钮提交所有数据?

1个回答

6

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

有一些与编辑相关的事件需要处理:BeginningEdit, CellEditEnding, PreparingCellForEdit

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

你可以获取 DataGridRow,从中循环遍历它的 DataGridCell。有许多教程可供参考。
对于您特定需求的确切方法: 1. 为所有列创建2个模板。
  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>
    

编码后

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

那其实就是我正在做的,将所有单元格切换到编辑模式。但如果失去焦点,它会不断地切换回来,有什么解决方法吗? - Tubc
CancelEdit() CommitEdit() 返回 true,但单元格仍保持编辑模式。 - Tubc
@Tubc 请查看我根据您的需求更新的确切答案。 - AnjumSKhan
太棒了,谢谢你解决我的问题并增加我在WPF方面的知识。 - Tubc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接