您的位置:首页 > 编程语言 > ASP

另类DATAGRID数据编辑修改 datagrid .asp.net

2006-08-04 16:12 316 查看
另类DATAGRID数据编辑修改
武汉 马建国
基于数据库的ASP.NET设计,使得众多企业和个人将原有的C/S应用系统转移到B/S模式下,.NET开发环境里提供的众多控件使得数据库的绑定和数据操作简便易行,其中Datagrid控件就是最常用的一个,为能在数据显示WEB页内同时实现数据的修改,Datagrid控件还提供了内嵌的编辑处理按钮组和对应的事件响应,本文将讨论Datagrid里数据修改的技术,并提供一种更为有效的数据编辑方式。
数据示例如下:
SQL>SELECT * FROM MJG_TEMP
IDNO CLASS NAME RESULT PASS
---------- ---------- ---------- ------ ----
2003060001 语文 陈国强 优 T
2003060002 数学 李小亮 中 T
2003060003 几何 杨梅 良 T
2003060004 英语 刘勇 差 F
2003060005 物理 刘青山 良 T
2003060006 化学 吴永请 差 F
下图为利用Datagrid控件产生的数据显示页面:



点选考生代码"200306003"记录对应的 "编辑"超链后,页面将变为图2所示的编辑页面:



上述图例的实现是Datagrid的常见应用,但它有以下不足:1、不能提供批次整屏修改。修改哪条记录必须先按"编辑"钮进入该条记录的编辑状态,修改完毕还必须按对应的"更新"钮保存修改;2、记录进入修改状态后,原有内容被清空不利于修改时的参照;3、修改编辑框缺省为TEXTBOX控件,对输入的修改值难以进行有效性判断,几乎无法提供数据检查和限制的能力;4、页面重载刷新频率较高,浏览者有"晃眼"的感觉,也加大了服务器负荷。点击"更新"钮保存修改后,页面将进行刷新,显示新的数据结果等待下一轮修改,如果我们在此例中对考试成绩有排序,原本位于第三条记录的考试成绩若被修改,将使得刷新后它出现在别的位置,记录一多用户就会感到"晃眼"记录位置变换了,若再遇网络(服务器)忙,用户的修改将陷入频繁等待中;5、三个事件定义不可少。在本例中编辑按钮事件OnEditCommand、更新按钮事件OnUpdateCommand和取消按钮事件OnCancleCommand需要进行响应代码设计,Datagrid并没有自动地来完成。
如何克服这些缺陷?回到象C/S方式那样灵活稳定的操控界面?我们需要首先了解Datagrid工作的原理,上例的Datagrid页面描述代码如下:

<asp:DataGrid id="DataGrid1" runat="server" AutoGenerateColumns="False" OnEditCommand=……>
……
<Columns>
<asp:BoundColumn DataField="idno" ReadOnly="True" HeaderText="考生代码">
</asp:BoundColumn>
<asp:BoundColumn DataField="name" ReadOnly="True" HeaderText="考生姓名">
</asp:BoundColumn>
<asp:BoundColumn DataField="class" ReadOnly="True" HeaderText="考试课目">
</asp:BoundColumn>
<asp:BoundColumn DataField="result" HeaderText="考试成绩">
</asp:BoundColumn>
<asp:BoundColumn DataField="pass" HeaderText="是否通过">
</asp:BoundColumn>
<asp:EditCommandColumn ButtonType="LinkButton" UpdateText="更新" HeaderText="修改" CancelText="取消" EditText="编辑">
</asp:EditCommandColumn>
</Columns>
</asp:DataGrid>

进行数据绑定的总共有五列,第六列为编辑按钮组。定义的前三列"考生代码"、"考生姓名"和"考试课目"都为"ReadOnly"属性,表示DataGrid处于编辑状态时,此三列不能被编辑,显示样式也不会发生变化;第四、五两列"考试成绩"与"通过与否"都是可编辑列,一旦DataGrid处于编辑状态,此两列就将由Label显示变为内定的TextBox编辑框,从而允许用户编辑。这种原理也就导致了DataGrid具有显示状态和编辑状态两种模式,页面在模式间切换时的刷新就不可避免,要想改变必须走"另类"的道路。因篇幅所限不详细介绍上例的事件代码。
我们将介绍的另类DataGrid编辑修改,将在以下方面进行改造:1、把允许编辑的第四、五两列由绑定列改变为模板列;2、将模板列的显示状态Label样式与编辑状态TextBox样式合并为兼具数据显示和修改功能的DropDownList或CheckBox等(TextBox本身也是显示、编辑兼具,但它缺少数据限制和自检的能力),利用这些控件的特性限制修改值的范围;3、取消第六列编辑按钮组及对应的事件,合并为界面上一个独立的按钮,该按钮的响应就是保存当前整屏修改后的数据。下面按步骤详细介绍。
一、绑定列变为模板列,同时取消第六列的按钮组,界面描述代码见下:
<asp:DataGrid id="DataGrid1" runat="server" AutoGenerateColumns="False"> ' 取消按钮组后,DataGrid自身已经没有事件响应的定义
……
<Columns> '开始定义列
<asp:BoundColumn DataField="idno" ReadOnly="True" HeaderText="考生代码">
<ItemStyle horizontalalign="Center"></ItemStyle>
</asp:BoundColumn>
<asp:BoundColumn DataField="name" ReadOnly="True" HeaderText="考生姓名">
<ItemStyle horizontalalign="Center"></ItemStyle>
</asp:BoundColumn>
<asp:BoundColumn DataField="class" ReadOnly="True" HeaderText="考试课目">
<ItemStyle horizontalalign="Center"></ItemStyle>
</asp:BoundColumn> ' 前三列没有发生改变,仍然是BoundColumn(绑定列)
<asp:TemplateColumn HeaderText="考试成绩"> ' 第四列定义开始
<ItemTemplate>
<asp:Label runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.result") %>'></asp:Label>
</ItemTemplate> ' 第四列在显示模式的定义,仍使用了label
<EditItemTemplate>
<asp:TextBox runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.result") %>'></asp:TextBox> ' 第四列在编辑模式时,其初始值取数据源当前记录的result字段
</EditItemTemplate> ' 第四列编辑模式的定义,仍使用了textbox
</asp:TemplateColumn> ' 第四列改变为TemplateColumn(模板列),
<asp:TemplateColumn HeaderText="是否通过"> '第五列定义开始
<ItemTemplate>
<asp:Label runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.pass") %>'></asp:Label>
</ItemTemplate>' 第五列在显示模式的定义,仍使用了label
<EditItemTemplate>
<asp:TextBox runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.pass") %>'></asp:TextBox> ' 第五列在编辑模式时,其初始值取数据源当前记录的pass字段
</EditItemTemplate> ' 第五列编辑模式的定义,仍使用了textbox
</asp:TemplateColumn>
</Columns> ' 列定义完毕
</asp:DataGrid>

二、合并显示模式与编辑模式
经过上面的调整,只完成了绑定列到模板列的转换,第四、五两列仍存在显示和编辑两种模式,下面将用DropDownList替换第四列、用CheckBox替换第五列的定义,描述代码如下:
……
<asp:TemplateColumn HeaderText="考试成绩"> ' 第四列定义开始
<ItemTemplate>
<asp:DropDownList id="DropDownList1" runat="server" Width="60px" selectedindex='<%# DataBinder.Eval(Container, "DataItem.result") %>'> ' 第四列被定义为DropDownList项,该对象的ID指定为DropDownList1,它只有五种可选值
<asp:ListItem Value="优">优</asp:ListItem>
<asp:ListItem Value="良">良</asp:ListItem>
<asp:ListItem Value="中">中</asp:ListItem>
<asp:ListItem Value="差">差</asp:ListItem>
<asp:ListItem Value="无">无</asp:ListItem>
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateColumn> ' 第四列没有了编辑模式,只存在显示模式
<asp:TemplateColumn HeaderText="是否通过"> '第五列定义开始
<ItemTemplate>
<asp:CheckBox id="CheckBox1" runat="server" text="通过" checked='<%# DataBinder.Eval(Container, "DataItem.pass") %>'></asp:checkbox> ' 第五列被定义为CheckBox项,该对象ID指定为CheckBox1,只有两种状态可选
</ItemTemplate> ' 第五列也没有了编辑模式,只有显示模式
</asp:TemplateColumn>
</Columns> ' 列定义完毕
</asp:DataGrid>

大家会问第四列被替换为DropDownList后,其selectedindex属性动态绑定到当前记录的result字段,前者是数字型取值,后者是字符串值,二者如何赋值?同样还有第五列,CheckBox的布尔型逻辑值Checked怎么被赋为字符串值?实际上我们在取值的SQL语句上也需要做出修改,程序代码如下:
sub show_data ' 在浏览界面上显示数据的过程
dim sql as string
dim mycomm As New OracleCommand() sql="select idno,class,name,decode(result,'优','0','良','1','中','2','差','3','4') as result,decode(pass,'T','true','false') as pass from mjg_temp"
Dim myadapter As New OracleDataAdapter()
myadapter.SelectCommand = new OracleCommand(sql,session("database")) 'session("database")为定义的数据库连接对象,以session变量的形式储存
dim mydataset as new dataset()
myadapter.fill(mydataset,"mytable")
datagrid1.datasource=mydataset.tables("mytable").defaultview
datagrid1.databind ' 将datagrid1绑定给SQL语句查询到的结果数据集,产生显示
session("database").close()
end sub
Sub Page_Load(sender As Object, e As EventArgs) ' 页面加载事件定义
if not ispostback then
show_data
end if
End Sub
由于数据库后台使用Oracle平台,因此在Asp.Net程序代码里定义使用了相应的Oracle数据库操控对象;SQL语句里的Decode函数也是针对Oracle的查询函数,其作用是当result字段值为'优'、'良'、'中'、'差'时,分别将结果转换为'0'、'1'、'2'、'3',为其它值时转换为'4';当pass字段值为'T'时,将结果转换为'true',否则转换为'false'。通过这样的转换,DropDownList和CheckBox就可以绑定到正确的参数值上了。(其它数据库平台也有类似DECODE的函数,此处不详述)。经过上述修改,我们将看到下面的Asp.Net运行界面:



"考试成绩"和"是否通过"两项与其它项一样正确地显示了初始取值,没有了Datagrid常见的编辑按钮后, 它们照样可以随时修改而且没有页面的重载刷新,修改后的数据保持在界面上可被继续修改,修改值的范围也被限制在DropDownList规定的范围内,不必担心可能的数据逻辑错误,界面的效果和可操作性也得到明显的改善。



三、保存修改事件的程序编写
界面设计好了,就只剩保存事件程序代码的编写,写代码时将依照这样的原理:对Datagrid里的"考试成绩"和"是否通过"项进行逐行取值,将DropDownList的当前selectedindex数值转换为对应的字符串值,将CheckBox的当前Checked逻辑值转换为对应的字符串值'T'或'F',以考生代码为检索条件进行数据表的修改操作,程序代码如下
Sub SaveButton_Click(sender As Object, e As EventArgs)
dim string_tem1 as string ' 定义字符串变量,用于存放考试成绩字符串值
dim string_tem2 as string ' 定义字符串变量,用于存放是否通过字符串值
Dim item As DataGridItem ' 定义DataGridItem对象,用于定位Datagrid里的每一行
dim mycontrol1 as Dropdownlist ' 定义Dropdownlist对象,用于定位Datagrid每行里的Dropdownlist
dim mycontrol2 as CheckBox ' 定义Checkbox对象,用于定位Datagrid每行里的Checkbox
dim mycomm As New OracleCommand()
mycomm.Connection = session("database")
session("database").open()
For Each item In dataGrid1.Items ' 此循环在Datagrid里处理每一行
mycontrol1 = item.findcontrol("dropdownlist1") ' findcontrol是Datagrid的行对象Items的方法
select case mycontrol1.selectedindex
case 0
string_tem1="优"
case 1
string_tem1="良"
case 2
string_tem1="中"
case 3
string_tem1="差"
case 4
string_tem1="无"
end select ' Case判断用于将Dropdownlist的当前选择序号转换为对应的成绩字符串值
mycontrol2 = item.findcontrol("checkbox1")
if mycontrol2.checked then string_tem2="T" else string_tem2="F" ' IF判断将checkbox的当前选择转换为对应的是否通过字符串T或F
mycomm.Commandtext = "update mjg_temp set result='"+string_tem1+"',pass='"+string_tem2+"' where idno='"+item.cells(0).text+"'" ' item.cells(0)即Datagrid当前行的第一列,其text属性就是所显示的值,这里就是考生代码,保存修改将以此作为记录定位条件
mycomm.executereader()
Next item
session("database").close()
show_data ' 保存修改完毕之后,再进行数据重新提取,用户浏览界面将重载刷新,子过程在上段代码中
End Sub

这里需要对为什么用FindControl函数进行一些说明:取Datagrid里某行某列的值,要先先定位行,指定Datagrid的Itemindex值后,Datagrid.items即为对应行,上例代码中因将遍历所有行,就没有指定Itemindex,当前行被赋给事先定义的item对象。item中包含多个列,取通常列的值,我们可使用Datagriditem对象的cells(i)属性,参数i为列号值,0代表第一列。当行中有特殊值(本例中就是第四列的Dropdownlist对象和第五列的Checkbox对象),就需要使用Datagriditem对象的Findcontrol方法,在当前行里查找指定ID的内嵌对象,找到后就可以引用它自身的属性和方法了。在本例中两对象的ID分别被指定为Dropdownlist1和Checkbox1(参见第三段代码)。
经过这番修改后,网页元件描述界面、SQL数据源查询语句和事件响应代码的修改全部结束,三部分的修改相互配合互为关联,此时再运行就可以通过统一的"保存修改"按钮实现数据的编辑存储了。



开发工具:XP + ASP.NET Web Matrix
数据库环境:Oracle 9i
运行环境:2000 Server + Microsoft .NET Framework + .NET Framework Data Provider for Oracle
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: