In my recent codeproject article on the DataGrid I described a number of techniques for handling the updates to DataTables which are bound to the grid. These examples all worked on the assumption that you want to keep your database synchronised with the DataGrid, with changes being committed on a row-by-row basis, i.e. when the user finishes editing a row the changes are written to the database. The WPF DataGrid operates in a row-oriented manner making this a relatively straightforward scenario to implement.

However, what if you want to commit changes on a cell-by-cell basis? Firstly, lets have a look at the problem in a bit more detail. The following code displays a DataGrid, together with a 'details' view. Note that IsSynchronizedWithCurrentItem is set to true so that the details view and currently selected item within the grid will remain synchronised:

<DockPanel DataContext="{Binding Source={StaticResource PersonData}}">

  <Border DockPanel.Dock="Bottom" Padding="10">
<Grid x:Name="RootElement">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="1.8*"/>
</Grid.ColumnDefinitions> <Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions> <Label Content="Forename:"/>
<TextBox Grid.Column="1" Text="{Binding Forename}"/> <Label Grid.Row="1" Content="Surname:"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Surname}"/> <Label Grid.Row="2" Content="Age:"/>
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Age}"/>
</Grid>
</Border> <dg:DataGrid ItemsSource="{Binding}" Name="dataGrid"
IsSynchronizedWithCurrentItem="true"/>
</DockPanel>

The 'PersonData' in this case is a DataTable that is constructed in the code-behind.

Now, with this example, if you make changes to a persons surname, then click on the age cell and make changes there, the changes in surname are not reflected in the details view below:

In the above example the user has entered the surname "Blunt" and has moved onto the age cell, however the changes are not reflected in the details view below.

Why is this?

The reason is that when you bind to a DataTable, you are actually binding to your DataTable's DefaultView, which is of type DataView. As a result, each row of your table will be bound to a DataRowView. If you look at the documentation for DataRowView you will find that it implements the IEditableObject interface which is the significant factor here. This interface allows you to perform trasnactional changes to your object, i.e. you can change the object's properties within a 'transaction', then commit then all in a single atomic action. By default, when you bind to a DataGrid this occurs when the user finishes editing a row, either by moving focus or hitting Enter. In order to allow cell-by-cell changes, we need to commit each time the user moves from one cell to the next in the currently selected row.

The DataGrid exposes a CellEditEnding event which looks like a good candidate for this, from the event arguments we can locate the current EditingElement (i.e. the TextBox which now occupies or cell that is in edit mode), the cell's Column and Row, and from here we can locate the Row.Item whcih is our bound DataRowView. You might think that we can just commit the change in this event handler, however, this is an 'Ending' event, not an 'Ended' event. In other words the value has not yet been written to the row. This catches me out far too often - as does its RowEditEnding counterpart!

So, if we cannot commit the edit here, how about the CurrentCellChanged event? however this event does not tell us which cell we just left. Although a simple combination of the two provides the effect we are after:

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

With this change in place, changes are committed cell-by-cell and the two view remain synchronised:

You can download an example project, wpfdatagridcellbycellcommits, changing the file extension from .doc to .zip.

Regards, Colin E.

WPF DATAGRID - COMMITTING CHANGES CELL-BY-CELL的更多相关文章

  1. xceed wpf datagrid

    <!--*********************************************************************************** Extended ...

  2. WPF DataGrid显格式

    Guide to WPF DataGrid formatting using bindings Peter Huber SG, 25 Nov 2013 CPOL    4.83 (13 votes) ...

  3. 编写 WPF DataGrid 列模板,实现更好的用户体验

    Julie Lerman 下载代码示例 最近我在为一个客户做一些 Windows Presentation Foundation (WPF) 方面的工作. 虽然我提倡使用第三方工具,但有时也会避免使用 ...

  4. WPF DataGrid 控件的运用

    WPF DataGrid 控件的运用 运行环境:Window7 64bit,.NetFramework4.61,C# 6.0: 编者:乌龙哈里 2017-02-23 参考: King Cobra 博客 ...

  5. WPF DataGrid 获取选中 一行 或者 多行

    WPF中DataGrid使用时,需要将其SelectedItem转换成DataRowView进行操作 然而SelectedItem 与SelectedItems DataGrid的SelectionU ...

  6. ios中自定义cell 设置cell的分组结构

    ios系统默认的cell并不能满足我们的需求 这个时候就需要自定义我们的cell 自定义cell为分组的时候 需要设置分组样式  以下是我常用分组的二种方法: 第一是 在自定义的UITableView ...

  7. WPF DataGrid常用属性记录

    WPF DataGrid常用属性记录 组件常用方法: BeginEdit:使DataGrid进入编辑状态. CancelEdit:取消DataGrid的编辑状态. CollapseRowGroup:闭 ...

  8. cell与cell之间的间距问题,以及section跟随屏幕滑动而滑动问题

    苹果在cell与cell之间默认没有间距,这样有时候不能满足我们界面要求,所以我们就需要将cell设置为分组模式(也就是每组一行或者多行,分为n组),然后我们就可以在代理中根据自己的需求设计cell之 ...

  9. WPF DataGrid某列使用多绑定后该列排序失效,列上加入 SortMemberPath 设置即可.

    WPF DataGrid某列使用多绑定后该列排序失效 2011-07-14 10:59hdongq | 浏览 1031 次  悬赏:20 在wpf的datagrid中某一列使用了多绑定,但是该列排序失 ...

随机推荐

  1. oracle 的PACKAGE恢复过程

    SELECT obj# FROM obj$ AS OF TIMESTAMP TO_TIMESTAMP('2016-06-30', 'YYYY-MM-DD') WHERE NAME = 'PFWZ_AP ...

  2. JS_ECMA基本语法中的几种封装的小函数-1

    今天给大家介绍js ECMA中几个封装的小函数以及一些常用的函数小案例: 1,找重复的函数 <script> //在数组里面找重复: function findInArr(n,arr){ ...

  3. 比较原声socket 、GCDAsyncSocket

    原声socket NSInputStream 输入流(OC)NSOutputStream 输出流(OC)1:通过c语言的输入输出流CFReadStreamRef/CFWirteStreamRef(输入 ...

  4. 安装CocoaPods报错 - [!] The dependency `AFNetworking (~> 3.1.0)` is not used in any concrete target.

    今天新机装cocopods时,等安装完毕发觉出现[!] The dependency `AFNetworking (~> 3.1.0)` is not used in any concrete ...

  5. 学习JNDI

    既然datasource对象有tomcat提供,那么我们如何在应用程序中获得它呢,tomcat把这个对象放在JNDI服务中, 并用一个名字把它关联起来,我们在应用程序中,只需通过JNDI搜索这个名字, ...

  6. 三、jQuery--Ajax基础--Ajax全接触--扩展知识(跨域)

  7. 二、JavaScript语言--JS基础--JavaScript进阶篇--JavaScript内置对象

    1.什么事对象 JavaScript 中的所有事物都是对象,如:字符串.数值.数组.函数等,每个对象带有属性和方法. 对象的属性:反映该对象某些特定的性质的,如:字符串的长度.图像的长宽等: 对象的方 ...

  8. select count(*)和select count(1)哪个性能高

    select count(*).count(数字).count(字段名)在相同的条件下是没有性能差别的,一般我们在统计行数的时候都会把NULL值统计在内的,所以这样的话,最好就是使用COUNT(*) ...

  9. 【PHP小项目使用MVC架构】

    小项目名称是雇员管理系统. mvc是一种项目的开发模式,中文名称为模式视图控制器,是强制程序员将数据的输入.处理.输出分开的一种开发模式. 在这个小项目中,控制器使用service作为后缀名. 项目u ...

  10. Code Review for SSIS package

    以下是我对SSIS包进行code review的一些建议,如果有其他更好的方案欢迎拍砖. A. 查看是否使用了最优的解决方案 1. 最优的结构视图 2. 解决方案,包,任务,组建,参数的命名使用了易读 ...