zoukankan      html  css  js  c++  java
  • 另类DATAGRID数据编辑修改

    另类DATAGRID数据编辑修改
    武汉 马建国
    2003-8-28 13:43:00

    基于数据库的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

  • 相关阅读:
    1136 A Delayed Palindrome (algorithm reverse(ans.begin,ans.end))
    1141 PAT Ranking of Institutions PAT甲级
    最近点对 (迭代器访问数据)
    1146 Topological Order PAT 甲级
    1151 1151 LCA in a Binary Tree PAT 甲级
    jQuery的基本使用
    案例:移动端返回顶部效果
    移动端轮播图(原生JS写法)
    移动端特效
    本地存储
  • 原文地址:https://www.cnblogs.com/fuyingke/p/453891.html
Copyright © 2011-2022 走看看