在 DataGrid 中编辑后直接保存实体

Posted

技术标签:

【中文标题】在 DataGrid 中编辑后直接保存实体【英文标题】:Save entity directly after edit in DataGrid 【发布时间】:2015-09-24 15:08:45 【问题描述】:

我使用DataGrid 将我的数据可视化给用户。编辑后,更新后的数据应直接存储到数据库中,无需使用任何“保存”按钮。

到目前为止,这是我的解决方案,它适用于所有 DataGrid 列,但 ComboBox 使用 EventTriggerInvokeCommandAction

<DataGrid ItemsSource="Binding Path=Animals, Mode=TwoWay,
                        UpdateSourceTrigger=PropertyChanged" SelectionMode="Single"
                        AutoGenerateColumns="False" CanUserSortColumns="True">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="RowEditEnding">
            <i:InvokeCommandAction Command="Binding SaveCommand" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <DataGrid.Columns>
        <DataGridTextColumn Header="EPC" Binding="Binding Epc, Mode=TwoWay,
                            UpdateSourceTrigger=PropertyChanged"/>
        <DataGridTextColumn Header="Visual ID" Binding="Binding VisualId, Mode=TwoWay,
                            UpdateSourceTrigger=PropertyChanged"/>
        <DataGridTextColumn Header="Geschlecht" Binding="Binding Gender, Mode=TwoWay,
                            UpdateSourceTrigger=PropertyChanged"/>
        <DataGridTemplateColumn Header="Bucht">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ComboBox ItemsSource=
"Binding DataContext.Pens,RelativeSource=RelativeSource AncestorType=x:Type view:AdministrationView"
                              DisplayMemberPath="Name"
                              SelectedItem="Binding Pen, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged"
                              SelectedValue="Binding Pen.PenId" 
                              SelectedValuePath="PenId"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

ComboBox 选择更改后,如何在我的视图模型中调用 SaveCommand

或者是否有更简单的解决方案来实现我想要的行为(每次编辑后自动保存到数据存储)?

【问题讨论】:

【参考方案1】:

如果您像这样添加另一个激活您的ICommandEventTrigger,您将获得所需的行为:

<DataGridTemplateColumn Header="Bucht">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <ComboBox ItemsSource="Binding DataContext.Pens, RelativeSource=RelativeSource AncestorType=x:Type view:AdministrationView" DisplayMemberPath="Name" SelectedItem="Binding Pen, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged" SelectedValue="Binding Pen.PenId" SelectedValuePath="PenId">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="SelectionChanged">
                            <i:InvokeCommandAction Command="Binding DataContext.SaveCommand, RelativeSource=RelativeSource AncestorType=x:Type view:AdministrationView" />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </ComboBox>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

【讨论】:

【参考方案2】:

在您的 ViewModel 中,我假设您已经像这样定义了您选择的项目?

object selectedPen; 
public object SelectedPen 
 
    get 
     
        return selectedPen; 
     
    set 
     
        if (selectedPen != value)
        
            selectedPen = value; 
            DoSave(); // insert saving logic here
            OnPropertyChanged("SelectedPen"); 
        
    
 

当设置器中的值发生变化时,您可以调用保存。

【讨论】:

我不确定我是否喜欢它...在 ViewModel 中有上下文(DoSave() 需要)。通常我会在用户界面中保留保存逻辑(想想明年你使用 SelectPen 会发生什么,我能理解为什么)。 对不起,什么? 是什么意思,想想明年你将使用 SelectPen 时会发生什么,我能理解为什么 个人意见。如果您通常不以这种方式使用 ViewModel,您可能会忘记(或者您的同事不知道)它节省了属性集。不过是个人意见吗…… 我同意尽量减少 getter/setter 中的逻辑的观点。但是上下文应该在ViewModelimo 中可用。 是的,视图模型可以通过工作单元/存储库模式访问上下文。【参考方案3】:

一种方法是在您的 ViewModel 上实现 IEditableObject 并实现 DataGrid.CellEditEndingDataGrid.CurrentCellChanged。 有关详细信息,请参阅 Colin Eberhardt 的 this 博客文章。

private DataRowView rowBeingEdited = null;

private void dataGrid_CellEditEnding(object sender,
                                  DataGridCellEditEndingEventArgs e)

    DataRowView rowView = e.Row.Item as DataRowView;
    rowBeingEdited = rowView;


private void dataGrid_CurrentCellChanged(object sender, EventArgs e)

    if (rowBeingEdited != null)
    
        rowBeingEdited.EndEdit();
    

【讨论】:

这会在我的视图模型和我的视图之间引入非常紧密的耦合,我想避免这种耦合。通过在我的示例代码中使用 EventTrigger,我在没有紧密耦合的情况下得到了相同的结果。 除了 IEditableObject 接口之外,View 和 ViewModel 之间没有耦合。这都是作用于视图元素的代码隐藏,隐式调用 DataContext 的 IEditableObject-Implementaion。您正在镜像 DataGrid 的内置功能。 啊,我明白了。感谢您的澄清。确实没有紧密耦合:-) 但我想知道这个解决方案是否与我正在使用的解决方案有什么不同。现在我的命令在事件“RowEditEnding”之后触发(参见上面的示例代码)。 使用此解决方案,您可以将提交应用到每个单元格,而无需修改模板。事实上,您可以将这段代码放在一个 Behavior 中并重用 ist 而不会有太多麻烦。是imo维护点少的解决方案。

以上是关于在 DataGrid 中编辑后直接保存实体的主要内容,如果未能解决你的问题,请参考以下文章

jquery easyui如何实现单击datagrid的某个格子,就可以直接编辑,离开后直接保存。

没有为 dojo 的 DataGrid 触发事件

EasyUi DataGrid中数据编辑方式及编辑后数据获取,校验处理

实体对象不能被多个 IEntityChangeTracker 实例引用 编辑 DataGrid 行

在 DataGrid 上编辑多个单元格,然后保存到数据库

datagrid中的结束编辑行失效