WPF DATAGRID - COMMITTING CHANGES CELL-BY-CELL
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的更多相关文章
- xceed wpf datagrid
<!--*********************************************************************************** Extended ...
- WPF DataGrid显格式
Guide to WPF DataGrid formatting using bindings Peter Huber SG, 25 Nov 2013 CPOL 4.83 (13 votes) ...
- 编写 WPF DataGrid 列模板,实现更好的用户体验
Julie Lerman 下载代码示例 最近我在为一个客户做一些 Windows Presentation Foundation (WPF) 方面的工作. 虽然我提倡使用第三方工具,但有时也会避免使用 ...
- WPF DataGrid 控件的运用
WPF DataGrid 控件的运用 运行环境:Window7 64bit,.NetFramework4.61,C# 6.0: 编者:乌龙哈里 2017-02-23 参考: King Cobra 博客 ...
- WPF DataGrid 获取选中 一行 或者 多行
WPF中DataGrid使用时,需要将其SelectedItem转换成DataRowView进行操作 然而SelectedItem 与SelectedItems DataGrid的SelectionU ...
- ios中自定义cell 设置cell的分组结构
ios系统默认的cell并不能满足我们的需求 这个时候就需要自定义我们的cell 自定义cell为分组的时候 需要设置分组样式 以下是我常用分组的二种方法: 第一是 在自定义的UITableView ...
- WPF DataGrid常用属性记录
WPF DataGrid常用属性记录 组件常用方法: BeginEdit:使DataGrid进入编辑状态. CancelEdit:取消DataGrid的编辑状态. CollapseRowGroup:闭 ...
- cell与cell之间的间距问题,以及section跟随屏幕滑动而滑动问题
苹果在cell与cell之间默认没有间距,这样有时候不能满足我们界面要求,所以我们就需要将cell设置为分组模式(也就是每组一行或者多行,分为n组),然后我们就可以在代理中根据自己的需求设计cell之 ...
- WPF DataGrid某列使用多绑定后该列排序失效,列上加入 SortMemberPath 设置即可.
WPF DataGrid某列使用多绑定后该列排序失效 2011-07-14 10:59hdongq | 浏览 1031 次 悬赏:20 在wpf的datagrid中某一列使用了多绑定,但是该列排序失 ...
随机推荐
- 躲避大龙(codevs 1961)
题目描述 Description 你早上起来,慢悠悠地来到学校门口,发现已经是八点整了!(这句话里有一个比较重要的条件) 学校共有N个地点,编号为1~N,其中1号为学校门口(也就是你现在所处的位置), ...
- python基础——使用元类
python基础——使用元类 type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的. 比方说我们要定义一个Hello的class,就写一个hello. ...
- PHP之MVC项目实战
本文主要包括以下内容 类文件自动加载 路径管理 页面跳转 注册自动加载方法 配置文件系统 cookie session 类文件自动加载 在PHP中使用别的类时,需要载入类文件,如果类很多的话,需要重复 ...
- 学习JNDI
既然datasource对象有tomcat提供,那么我们如何在应用程序中获得它呢,tomcat把这个对象放在JNDI服务中, 并用一个名字把它关联起来,我们在应用程序中,只需通过JNDI搜索这个名字, ...
- MyEclipse生成WAR包并在Tomcat下部署发布(转发)
从来没有想过web项目还能打包的,但是有要求,就不得不去实现,在网上找了一下,发现挺简单的. 首先是使用MyEclipse将web项目打包,如下图所示. 右键选中项目,选择export. 然后选择J2 ...
- 三、jQuery--jQuery基础--jQuery基础课程--第7章 jQuery 动画特效
1.调用show()和hide()方法显示和隐藏元素 show()和hide()方法用于显示或隐藏页面中的元素,它的调用格式分别为:$(selector).hide(speed,[callback]) ...
- 设计模式学习之迭代器模式(Iterator,行为型模式)(17)
参考地址:http://www.cnblogs.com/zhili/p/IteratorPattern.html 一.介绍迭代器是针对集合对象而生的,对于集合对象而言,必然涉及到集合元素的添加删除操作 ...
- Win10开机提示Resume from Hibernation该怎么办?
Windows10系统的电脑开机提示:Resume from Hibernation(从休眠恢复),这是电脑没有真正关机,而是上次关机时进入了[休眠状态],所以开机时提示:从休眠恢复.如何解决Wind ...
- RecyclerView导入依赖包
1. eclipse 上的导入: 如下进入Android SDK的如下路径, \android-sdk\extras\android\m2repository\com\android\support\ ...
- Android浏览本地 API文档 + 解决页面加载慢的问题
火狐浏览器安装离线浏览插件: 用浏览器打开index.html文件,你会发现加载的很慢,原因你懂的,为此,我们可以通过离线的方式 查看本地API文档,用火狐浏览器 + Work Offline插 ...