基类、接口的应用——表单控件:一次添加、修改一条记录,一次修改多条记录。(上)

好久没发帖子了,又加了不少的功能呀。(图片仅是测试,不代表什么表情。)

本来我也想写一个2007的总结的,但是看到很多人都写了,我就不凑热闹了,写点和代码有关系的吧。

写作原因:

1、在项目里做得最多的操作恐怕就是保存数据了,总是要写一大堆的代码,能不能简单一点呢?2005来了,似乎可以减少一些代码,但是03里怎么办呢?

2、基类、接口、策略模式,好多高手都讨论过了,但是都是理论上的,在实践中如何应用呢?在webform 里面又怎么使用呢?

目的:

1、做一个“控件”来应对各种表单的录入,包括一次保存一条记录、一次保存多条记录。

2、写一下我对基类、接口、策略模式的理解,请各位高手批批。通过对一个实际中的例子的讨论,可以让新同学更好的理解吧。

针对的框架:

目前只考虑 asp.net1.1  (webform)。

先贴个图片,就是这样的表单

[开始了]

1、取值问题

表单里会有很多种控件,每一种控件的取值方法又不太一致,有的叫做 “Text”,有的叫做“SelectedValue”,甚至有的还要自己在写几行代码才行(比如 CheckBoxList)。

那么怎么才能让取值更简单一点呢?我想写一个方法(GetValue)来获取用户输入的数据,而且在取值的时候不必关心是什么控件,一个GetValue,就把值得到了,管它是什么控件呢!

如果用基类的话就要在控件的“共有”基类里面加一个方法,但是这个“共有”的基类也不是太好找,再有呢在.net框架里加点东东好像也不是太容易(或者是我学艺不精)。

我想到的解决方法呢就是使用接口。

先定义一个接口:IGetControlValue

Public Interface IGetControlValue



    ReadOnly Property ControlKind() As String

    Function GetControlValue() As String

        

End Interface

 然后呢再写几个自定义服务器控件(比如文本控件、下拉列表框了什么的),让他们继承这个接口。 目前我写了五个这样的控件:HBSTextBox 、HBSCheckBox 、HBSCheckBoxList 、HBSDropDownList 、HBSRadioButtonList  他们都继承了IGetControlValue。 控件比较多,我就只贴出 HBSCheckBoxList 的代码吧,其他的都是类似的写法。

<ToolboxData("<{0}:HBSCheckBoxList runat=server></{0}:HBSCheckBoxList>")> _

 Public Class HBSCheckBoxList

    Inherits System.Web.UI.WebControls.CheckBoxList

    Implements IGetControlValue



#Region "实现接口"

    <Bindable(True), Category("默认值"), DefaultValue(""), Description("获取控件类别")> _

    ReadOnly Property ControlKind() As String Implements IGetControlValue.ControlKind

        Get

            Return ""

        End Get

    End Property



    Public Function GetValue() As String Implements IGetControlValue.GetControlValue

        Return Me.GetSelectedValue



    End Function

#End Region





#Region "初始化 OnInit。设置CssClass、DataValueField、DataTextField、"

    Protected Overrides Sub OnInit(ByVal e As EventArgs)

        Me.CssClass = "chk"

        Me.DataValueField = "ID"

        Me.DataTextField = "txt"

        Me.Font.Size = FontUnit.Point()

    End Sub

#End Region



    '返回选择的ID值,用 , 分隔

#Region "函数实现  GetSelectedValue"

    Public Function GetSelectedValue() As String

        Dim item As ListItem

        Dim tmpStr As String = ""

        For Each item In Me.Items

            If item.Selected Then

                tmpStr &= item.Value & ","

            End If

        Next

        tmpStr = tmpStr.TrimEnd(",")

        Return tmpStr

    End Function

#End Region

(什么?您问为什么还有一个 GetSelectedValue(),没办法,这个是以前就实现了的,接口是后加的,为了保持向下兼容)  好了取值的问题基本解决了。 2、寻找控件。 如果加了接口之后还是 this.Txt1.GetValue(); 或者  ((IGetControlValue)Txt1).GetControlValue();那就没什么意思了。 我想达到的是  ((IGetControlValue)Page.FindControl("控件ID")).GetControlValue(); 这样做的好处是我只要知道控件的ID就可以得到数据,而不必去关心到底是什么控件,取值上有没有什么特殊的地方。 另外呢我还可以做一个循环,把控件ID放到一个数组里面,然后循环一下就可以了。控件(字段)再多我也不怕了,代码行数不会跟随字段的增加而增加。 3、开始保存数据(单条数据)。 在这里呢建议先看一下我以前发的一个帖子。 其实添加数据也可以这样简单——表单的第一步抽象(针对数据访问层)《怪怪设计论: 抽象无处不在 》有感 具体代码如下:

#region 添加数据

        private void Btn_Save2_Click(object sender, System.EventArgs e)

        {

            //设置字段名

            string[] str1 = new string[];

            str1[] = "TextBox";

            str1[] = "CheckBox";

            str1[] = "RadioButtonList";

            str1[] = "CheckBoxList";

            str1[] = "DropDownList";



            //设置控件ID

            string[] str2 = new string[];

            str2[] = "Txt2";

            str2[] = "Chk2";

            str2[] = "rdLst2";

            str2[] = "chkLst2";

            str2[] = "Lst2";



            //取值用的数组

            string[] str = new string[];



            HBS.Controls.IGetControlValue vv ;

            

            for (int i= ;i<str1.Length ;i++)

            {

                vv = (IGetControlValue)base.GetControl(str2[i],-);

                str[i] = vv.GetControlValue();

            }



            //添加数据

            dal.InsertDataStr("_TestInterface",str1,str);

            

            //弹出提示

            Functions.PageRegisterAlert(Page,"添加成功");

        

        }

        #endregion

(自我感觉还是挺简洁的,dal.InsertDataStr("_TestInterface",str1,str); 是调用数据访问层里的函数,而这个“数据访问层”是通用的,已经编译成dll,可以随时调用)。 4、保存多条数据。 上面说的是一次保存一条数据,那么要一次保存多条怎么办呢?这里需要DataGrid来帮忙了。 拖一个DataGrid出来,然后做一下设置,加几个模版类。 然后呢保存代码如下:

#region 一次修改多条数据

        private void Btn_Save_Click(object sender, System.EventArgs e)

        {

            //保存数据

            FormTableCntrlInfo[] cInfo = new FormTableCntrlInfo[];

    

            cInfo[].FieldName = "TextBox";        //设置字段名

            cInfo[].FieldName = "CheckBox";

            cInfo[].FieldName = "RadioButtonList";

            cInfo[].FieldName = "CheckBoxList";

            cInfo[].FieldName = "DropDownList";



            cInfo[].ControlID = "Txt1";        //设置控件ID

            cInfo[].ControlID = "Chk1";

            cInfo[].ControlID = "rdLst";

            cInfo[].ControlID = "chkLst";

            cInfo[].ControlID = "Lst";



            //设置控件的列索引,就是控件在DataGrid的第几行。

            cInfo[].ColumnIndex = ;        

            cInfo[].ColumnIndex = ;

            cInfo[].ColumnIndex = ;

            cInfo[].ColumnIndex = ;

            cInfo[].ColumnIndex = ;



            FormTableSaveData form = new FormTableSaveData();

            form.dal = dal;                        //设置数据访问层的实例

            form.TableName = "_TestInterface";    //设置表名

            string err = form.SaveDataByDataGrid(ref DG,ref cInfo,"testID={0}");  //修改数据



            if (err.Length >)

            {

                Functions.PageRegisterAlert(Page,"保存时出现以外,请与管理员联系。");

                return;

            }

            

            Functions.PageRegisterAlert(Page,"保存成功");

        }

        #endregion

这里保存了五个字段的记录,怎么样代码不是太多吧。 最大的优点就是:当控件在DataGrid的列的位置发生变化的时候,修改是很方便的。 什么?您问取值的地方在哪里?已经被我封装起来了。 form.SaveDataByDataGrid 是一个 针对DataGrid 来说通用的方法,只要你是用DataGrid来“绘制”页面的话就可以使用这个方法,不必每次(或每个项目)都写一遍。 还是贴一下  SaveDataByDataGrid 的代码吧。

Public Class FormTableSaveData



    Public dal As DataAccessLayer           '数据访问层

    Public TableName As String = ""         '添加、修改用的表名





#Region "保存DataGrid里的全部数据"

    Public Function SaveDataByDataGrid(ByRef DG As DataGrid, ByRef cInfo() As FormTableCntrlInfo, ByVal Query As String) As String



        Dim item As DataGridItem

        For Each item In DG.Items

            If item.ItemType <> ListItemType.Header And item.ItemType <> ListItemType.Footer Then

                SaveDataByDataGridItem(item, cInfo, Query)

            End If

        Next





    End Function

#End Region



#Region "保存DataGrid里的一条数据"



    Public Function SaveDataByDataGridItem(ByRef item As DataGridItem, ByRef cInfo() As FormTableCntrlInfo, ByVal Query As String) As String

        Dim i As Int32

        Dim tmpIndex As Int32

        Dim ctrlIndex As Int32 = 



        Dim iValue As IGetControlValue



        For i =  To item.Cells.Count - 

            '寻找对应的下标

            ctrlIndex = -

            For tmpIndex =  To cInfo.Length - 

                If i = cInfo(tmpIndex).ColumnIndex Then

                    ctrlIndex = tmpIndex

                    Exit For

                End If

            Next



            If ctrlIndex > - Then



                Select Case cInfo(ctrlIndex).ControlKind

                    Case "", "", "", "", "", "", "", ""

                        '文本框、多行文本、密码、日期文本、下拉列表 、复选框、单选组、多选组

                        '"201",  "202",   "203",  "204",   "205",    "208",   "209",   "210"

                        iValue = item.Cells(cInfo(ctrlIndex).ColumnIndex).FindControl(cInfo(ctrlIndex).ControlID)

                        If iValue Is Nothing Then

                            PublicClass.ResponseWrite("没有找到[" & cInfo(ctrlIndex).ControlID & "]这个控件", False)

                        Else

                            cInfo(ctrlIndex).FieldValue = iValue.GetControlValue()

                        End If



                    Case ""      ' 级联下拉列表()  



                        Dim tmpSplit() As Char

                        tmpSplit() = "|"

                        tmpSplit() = ","

                        Dim uLst As UniteDropDownList = CType(item.Cells(cInfo(ctrlIndex).ColumnIndex).FindControl(cInfo(ctrlIndex).ControlID), UniteDropDownList)

                        If uLst Is Nothing Then

                            PublicClass.ResponseWrite("没有找到[" & cInfo(ctrlIndex).ControlID & "]这个控件", False)

                        Else

                            Dim myID() As String = uLst.ListOtherSelectedValue.Split(tmpSplit)

                            Dim j As Int32 = 

                            For j =  To myID.Length

                                cInfo(i).FieldValue = myID(j)

                                ctrlIndex += 

                                i += 

                            Next

                            ctrlIndex -= 

                            i -= 

                        End If



                        'Case "207"      ' 单选()



                    Case ""      ' HTML_FreeTextBox() 

                        Dim ftb As FreeTextBoxControls.FreeTextBox = CType(item.Cells(cInfo(ctrlIndex).ColumnIndex).FindControl(cInfo(ctrlIndex).ControlID), FreeTextBoxControls.FreeTextBox)

                        If ftb Is Nothing Then

                            PublicClass.ResponseWrite("没有找到[" & cInfo(ctrlIndex).ControlID & "]这个控件", False)

                        Else

                            cInfo(ctrlIndex).FieldValue = ftb.Text

                            cInfo(ctrlIndex).FieldValue = cInfo(ctrlIndex).FieldValue.Replace("'", "''")

                            cInfo(ctrlIndex).FieldValue = cInfo(ctrlIndex).FieldValue.Replace("script", "script")

                        End If





                    Case ""      ' HTML_CuteEdit()



                    Case ""  '空行

                        cInfo(ctrlIndex).FieldValue = "_n_"



                End Select



                ctrlIndex += 

            End If



        Next



        '取值结束,保存数据

        Dim aa As Int32

        Dim tmpQuery = Query



        For aa =  To Query.Split("{").Length - 

            tmpQuery = tmpQuery.Replace("{" & aa & "}", item.Cells(aa).Text)

        Next



        'Query = Query.Replace("{0}", item.Cells(0).Text)

        ' PublicClass.ResponseWrite(tmpQuery & "<BR>", False)

        dal.UpdateDataByFormTableCntrlInfo(TableName, cInfo, tmpQuery)



        Return dal.ErrorMsg



    End Function



#End Region





End Class

这样就基本OK了。今天刚刚写好,可能会有一些错误,另外还有一个问题没有说,还有几个延伸的地方。放在下集在说吧。 (上集完成)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏更流畅、简洁的软件开发方式

[自定义服务器控件] 第二步:下拉列表框。

前面发了一个文本框的,这回发一个下拉列表框。 一般在写自定义控件之前都要考虑一下原来的控件(系统代的)有什么优缺点,有哪些功能是我想要的,但是自带的控件没有提...

3066
来自专栏软件开发

前端MVC Vue2学习总结(三)——模板语法、过滤器、计算属性、观察者、Class 与 Style 绑定

Vue.js 使用了基于 HTML 的模版语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,...

63410
来自专栏跟着阿笨一起玩NET

编写自定义控件之下拉式属性

 //*****************************************************************************...

782
来自专栏Angular&服务

Angular2 组件(页面)之间如何传值

在Angular 2中,数据和事件变化检测从上到下发生从<b>父级到子级。</b>

7125
来自专栏Golang语言社区

go语言中json转成map结构

package main import ( "encoding/json" "fmt" ) //把请求包定义成一个结构体 type Reques...

5036
来自专栏熊二哥

Javascript快速入门(上篇)

Javascript的熟练之路,小弟来了。 ? JavaScript简介:JavaScript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,...

2015
来自专栏源码之家

EXCEL取消合并且等于原合并值

1614
来自专栏与神兽党一起成长

手工实现表单重置的部分功能

首先我必须说几乎所有的人都不需要自己实现表单重置的功能,表单重置功能只需要一个reset类型的input就足够了。<input type="reset" />

1773
来自专栏青青天空树

MFC-简单的函数使用

1.   MessageBox(str);很简单的一个函数,该函数参数为字符串.用来弹出一个窗口显示str的内容,str为一个字符串.

1644
来自专栏互联网软件技术

将表格导出为excel

1205

扫码关注云+社区

领取腾讯云代金券