分享
 
 
 

VB.NET中“数据窗体向导”所生成的“添加”代码的改进

王朝vb·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

在数据库应用程序开发中,我们知道数据操作的主要任务是:“浏览、编辑、删除、添加记录”,利用VB.NET的“数据窗体向导”可以帮助我们迅速创建实现上述功能的Windows 窗体及相关代码,这种自动生成的代码完全具有实用性和可借鉴性。然而笔者在使用中发现,在“数据窗体向导”的操作过程中,如果我们选择的是“单个控件的单个记录”显示样式,假如控件绑定到的数据源中的字段又有不允许为Null值的话,运行自动生成的窗体,单击“添加”后会出现错误。

为了避免该错误,已有的解决方法是:“添加”功能不使用“数据窗体向导”生成的代码,而是新建一窗体然后采用非数据绑定结构来单独实现“添加”功能。笔者经过探索发现完全没有必要另建窗体,只需对“数据窗体向导”生成的代码进行适当的改进就可以在同一个窗体中同时实现“浏览、编辑、删除、增加”功能,如下通过实例说明(注:开发工具为Microsoft Visual Studio .NET 2003 ,示例数据库是SQL Server 2000中的“pubs”;以下代码虽然以VB为例,但方法同样适用于VS.NET中的其它开发语言)。

一、 有不允许为Null值的字段绑定到非TextBox类控件

如下图一所示就是属于这类情况,窗体中“contract”旁的复选框控件绑定到的列字段“contract”就不允许有Null值。运行该窗体并“加载”后,单击“添加”可以“新增”记录(编号为24的记录),但单击导航按钮(比如最后一条“>>”),记录位置不能移到该新增记录。

图一窗体及代码是由“数据窗体向导”自动生成(菜单操作:“文件/添加新项”,然后选 “数据窗体向导”),数据窗体实例的名称是“DEMO”,数据集的名称是“DS”,数据连接是以SQL Server 2000中的“pubs” 示例数据库为例,选择“authors”表,选择“单个控件的单个记录”显示样式,其它都采用“数据窗体向导”的默认值。图一这一类情况的改进方法是首先修改“添加”按钮的单击事件处理代码,如下所示。

Private Sub btnAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdd.Click

Try

Me.BindingContext(objDS, "authors").EndCurrentEdit()

Me.BindingContext(objDS, "authors").SuspendBinding() '临时挂起数据绑定

Me.BindingContext(objDS, "authors").AddNew() '增加新记录

'如下两层循环先找出authors表中不允许为null的列字段,然后找出绑定到该字段的binding对象,

'依据绑定到的控件属性不同来为新增记录中不能为空的字段赋不同初始值

Dim i As Integer

For i = 0 To objDS.authors.Columns.Count - 1 '遍历authors表中所有列字段

'找出authors表中不允许为null的列字段

If objDS.Tables("authors").Columns(i).AllowDBNull = False Then

Dim j As Integer

For j = 0 To Me.BindingContext(objDS, "authors").Bindings.Count - 1 '遍历所有Binding对象

'找出绑定到不允许为null字段的binding对象

If Me.BindingContext(objDS, "authors").Bindings(j).BindingMemberInfo.BindingField = _

objDS.authors.Columns(i).ColumnName Then

'如果绑定到的控件的属性为Text

If BindingContext(objDS, "authors").Bindings(j).PropertyName() = "Text" Then

'新增加记录中不能为null的字段赋初始值"",该语句还可用紧挨着的注释语句代替!

Me.BindingContext(objDS, "authors").Current(j) = ""

'BindingContext(objDS, "authors").Current(i) = BindingContext(objDS, "authors"). _

' Bindings(j).Control.Text()

Exit For '退出当前For循环,寻找下一个不允许为null的列字段

Else

'如果绑定到的控件的属性为Checked(其它绑定属性…,应该可以自己仿照搞定了.)

If BindingContext(objDS, "authors").Bindings(j).PropertyName = "Checked" Then

'新增加记录中不能为null的字段赋初始值True, 该语句可用紧挨着的4行注释语句代替!

Me.BindingContext(objDS, "authors").Current(j) = True

'Dim tmpobj As Object

'tmpobj = BindingContext(objDS, "authors").Bindings(j).Control

'tmpobj = CType(tmpobj, CheckBox)

'Me.BindingContext(objDS, "authors").Current(j) = tmpobj.checked

Exit For '退出当前For循环,寻找下一个不允许为null的列字段

End If

End If

End If

Next

End If

Next

'如新增加行不需利用row_changing事件进行数值验证,可启用下边注释行

'Me.BindingContext(objDS, "authors").EndCurrentEdit()

Me.BindingContext(objDS, "authors").ResumeBinding() '恢复数据绑定

'移动表中位置到新增加记录

Me.BindingContext(objDS, "authors").Position = Me.BindingContext(objDS, "authors").Count - 1

Catch eEndEdit As System.Exception

System.Windows.Forms.MessageBox.Show(eEndEdit.Message)

Me.BindingContext(objDS, "authors").CancelCurrentEdit() '出错,取消新增加行

Me.BindingContext(objDS, "authors").ResumeBinding()

End Try

Me.objDS_PositionChanged()

End Sub

以上btnAdd.Click事件处理代码改进的实质是:临时挂起数据绑定,新增一记录,然后对记录中不允许为Null值的列字段赋值(如不需利用rowchanging事件进行新增记录数据检验,也可仅对不允许null值且不能绑定到文本框TextBox的字段赋初值),最后恢复数据绑定。

此外,还要对四个导航按钮(第一条、上一条、下一条、最后一条)的单击事件处理程序作如下修改(为了简化,此处只以上一条“<”按钮的单击事件处理程序为例,其它按钮仿照)。

Private Sub btnNavPrev_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNavPrev.Click

Try '采用try语句进行错误处理(Null及唯一性)

Me.BindingContext(objDS, "authors").Position = (Me.BindingContext(objDS, "authors").Position - 1)

Catch ex As Exception

MessageBox.Show(ex.Message) '显示错误信息

Exit Sub '如有错误,不许移动位置

End Try

Me.objDS_PositionChanged()

End Sub

如果想利用rowchanging事件对新增加或编辑…记录进行数据检验(建议),则还需要增加如下rowchanging事件处理代码。

Private Sub row_changing(ByVal sender As Object, ByVal e As DS.authorsRowChangeEvent)

'对新增加行进行数值验证

If e.Action = DataRowAction.Add Then

'此处为了简单,以字段au_id不能为""为例

If editau_id.Text = "" Then

Throw (New Exception("数据不能为空"))

End If

End If

'还可以对记录的编辑值进行验证

'If e.Action = DataRowAction.Change Then

'此处填入编辑验证代码

'End If

'其它验证,依照上面加入吧

End Sub

要启动rowchanging事件处理,请在程序的适当位置加入如下语句(本人是加在LoadDataSet()方法中的语句objDS.Merge(objDataSetTemp)后面)。

AddHandler objDS.authors.authorsRowChanging, AddressOf row_changing

二、 虽然有不允许为Null值的字段,但全部都能绑定到TextBox类控件

为了说明方便,我们再利用“数据窗体向导”新建一窗体(注:新窗体可以建在上一个窗体的同一个项目中,数据窗体的名称是“demo2”,新建数据集名称为“ds2”),该数据窗体是绑定到“pubs”数据库中的“employee”表。如图二所示,该表中的所有不允许为Null值的字段都能绑定到TextBox类控件。

运行该窗体后,单击“加载”后可以新增记录(编号为44的记录),但是如果新增记录后不输入任何值而单击任一导航按钮(比如上一条“<”),会出现如图三所示错误。

这一类错误较轻,完全可以采用第一种情况的解决方法,当然如果你嫌多的话,还可以采用如下更为简单的方法: 在“数据窗体向导”自动生成的代码中,只需对四个导航按钮(第一条、上一条、下一条、最后一条)的单击事件处理程序代码进行适当修改(注意:还是按照第一种情况中四个导航按钮的代码修改方法进行修改),其它代码不变也不增加,一切就0k了,此时再试试,你会见到如图四友好的界面,提示你必须对不允许空值的列字段进行输入,然后才能改变记录位置。

三、 总结

当有不许Null值的字段绑定到数据窗体上时,为了避免出现新增记录错误,在上面笔者介绍了可以在代码中找到解决办法,另外我们还可以在数据集中找到解决办法:“在数据集的架构中,对不允许Null值的列字段给它设置一默认值即可”,当然具体采用哪种解决方法还是请你根据实际情况灵活选择。

上面给出了第一种情况的主要解决代码,末尽之处请大家参照下边完整代码。

Public Class DEMO

Inherits System.Windows.Forms.Form

'为了简化,“Windows 窗体设计器生成的代码”去掉了,记住在“数据窗体向导”执行时按照以下要求即可。

'数据窗体实例的名称是“DEMO”,数据集的名称是“DS”,数据连接是以SQL Server 2000中

'的“pubs” 示例数据库为例,选择“authors”表、“单个控件的单个记录”显示样式,其它都采用的默认值。

Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click

Me.BindingContext(objDS, "authors").CancelCurrentEdit()

Me.objDS_PositionChanged()

End Sub

Private Sub btnDelete_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDelete.Click

If (Me.BindingContext(objDS, "authors").Count > 0) Then

Me.BindingContext(objDS, "authors").RemoveAt(Me.BindingContext(objDS, "authors").Position)

Me.objDS_PositionChanged()

End If

End Sub

Private Sub btnAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdd.Click

Try

Me.BindingContext(objDS, "authors").EndCurrentEdit()

Me.BindingContext(objDS, "authors").SuspendBinding()

Me.BindingContext(objDS, "authors").AddNew()

Dim i As Integer

For i = 0 To objDS.authors.Columns.Count - 1

If objDS.Tables("authors").Columns(i).AllowDBNull = False Then

Dim j As Integer

For j = 0 To Me.BindingContext(objDS, "authors").Bindings.Count - 1

If Me.BindingContext(objDS, "authors").Bindings(j).BindingMemberInfo.BindingField = _

objDS.authors.Columns(i).ColumnName Then

If BindingContext(objDS, "authors").Bindings(j).PropertyName() = "Text" Then

Me.BindingContext(objDS, "authors").Current(j) = ""

'BindingContext(objDS, "authors").Current(i) = BindingContext(objDS, "authors"). _

' Bindings(j).Control.Text()

Exit For

Else

If BindingContext(objDS, "authors").Bindings(j).PropertyName = "Checked" Then

Me.BindingContext(objDS, "authors").Current(j) = True

'Dim tmpobj As Object

'tmpobj = BindingContext(objDS, "authors").Bindings(i).Control

'tmpobj = CType(tmpobj, CheckBox)

'Me.BindingContext(objDS, "authors").Current(i) = tmpobj.checked

Exit For

End If

End If

End If

Next

End If

Next

Me.BindingContext(objDS, "authors").ResumeBinding()

Me.BindingContext(objDS, "authors").Position = Me.BindingContext(objDS, "authors").Count - 1

Catch eEndEdit As System.Exception

System.Windows.Forms.MessageBox.Show(eEndEdit.Message)

Me.BindingContext(objDS, "authors").CancelCurrentEdit()

Me.BindingContext(objDS, "authors").ResumeBinding()

End Try

Me.objDS_PositionChanged()

End Sub

Private Sub btnUpdate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUpdate.Click

Try

'尝试更新数据源。

Me.UpdateDataSet()

Catch eUpdate As System.Exception

'在此处添加错误处理代码。

'显示错误信息(如果有)。

objDS.RejectChanges() '我增加的语句

System.Windows.Forms.MessageBox.Show(eUpdate.Message)

End Try

Me.objDS_PositionChanged()

End Sub

Private Sub btnLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLoad.Click

Try

'尝试加载数据集。

Me.LoadDataSet()

Catch eLoad As System.Exception

'在此处添加错误处理代码。

'显示错误信息(如果有)。

System.Windows.Forms.MessageBox.Show(eLoad.Message)

End Try

Me.objDS_PositionChanged()

End Sub

Private Sub btnNavFirst_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNavFirst.Click

Try

Me.BindingContext(objDS, "authors").Position = 0

Catch ex As Exception

MessageBox.Show(ex.Message)

Exit Sub

End Try

Me.objDS_PositionChanged()

End Sub

Private Sub btnLast_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLast.Click

' Me.BindingContext(objDS, "authors").Position = (Me.objDS.Tables("authors").Rows.Count - 1)

Try

'注意下一条语句我进行了修改

Me.BindingContext(objDS, "authors").Position = Me.BindingContext(objDS, "authors").Count - 1

Catch ex As Exception

MessageBox.Show(ex.Message)

Exit Sub

End Try

Me.objDS_PositionChanged()

End Sub

Private Sub btnNavPrev_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNavPrev.Click

Try '采用try语句进行错误检查(Null及唯一性)

Me.BindingContext(objDS, "authors").Position = (Me.BindingContext(objDS, "authors").Position - 1)

Catch ex As Exception

MessageBox.Show(ex.Message)

Exit Sub '如有错误,不许移动位置

End Try

Me.objDS_PositionChanged()

End Sub

Private Sub btnNavNext_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNavNext.Click

'If BindingContext(objDS, "authors").Position = BindingContext(objDS, "authors").Count - 1 Then '可不要

' MessageBox.Show("数据到顶了!")

' Exit Sub

'End If

Try

Me.BindingContext(objDS, "authors").Position = (Me.BindingContext(objDS, "authors").Position + 1)

Catch ex As Exception

MessageBox.Show(ex.Message)

Exit Sub

End Try

Me.objDS_PositionChanged()

End Sub

Private Sub objDS_PositionChanged()

Me.lblNavLocation.Text = (((Me.BindingContext(objDS, "authors").Position + 1).ToString + " 的 ") _

+ Me.BindingContext(objDS, "authors").Count.ToString)

End Sub

Private Sub btnCancelAll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancelAll.Click

Me.objDS.RejectChanges()

Me.objDS_PositionChanged() '我增加的语句

End Sub

Public Sub UpdateDataSet()

'创建一个新数据集来保存对主数据集所做的更改。

Dim objDataSetChanges As DS = New DS

'停止当前的任何编辑。

Me.BindingContext(objDS, "authors").EndCurrentEdit()

'获取对主数据集所做的更改。

objDataSetChanges = CType(objDS.GetChanges, DS)

'检查是否做了任何更改。

If (Not (objDataSetChanges) Is Nothing) Then

Try

'需要做一些更改,所以尝试通过调用 update 方法

'和传递数据集以及任何参数来更新数据源。

Me.UpdateDataSource(objDataSetChanges)

objDS.Merge(objDataSetChanges)

objDS.AcceptChanges()

Catch eUpdate As System.Exception

'在此处添加错误处理代码。

Throw eUpdate

End Try

'添加代码以检查返回的数据集中是否有任何可能已被

'推入到行对象错误中的错误。

End If

End Sub

Public Sub LoadDataSet()

'创建一个新数据集以保存从 FillDataSet 调用返回的记录。

'使用了一个临时数据集,这是因为填充现有的数据集

'需要重新绑定数据绑定。

Dim objDataSetTemp As DS

objDataSetTemp = New DS

Try

'尝试填充临时数据集。

Me.FillDataSet(objDataSetTemp)

Catch eFillDataSet As System.Exception

'在此处添加错误处理代码。

Throw eFillDataSet

End Try

Try

'清空数据集中的旧记录。

objDS.Clear()

'将记录合并到主数据集中。

objDS.Merge(objDataSetTemp)

'我在此处加入rowchanging事件

AddHandler objDS.authors.authorsRowChanging, AddressOf row_changing

Catch eLoadMerge As System.Exception

'在此处添加错误处理代码。

Throw eLoadMerge

End Try

End Sub

Public Sub UpdateDataSource(ByVal ChangedRows As DS)

Try

'在有挂起的更改时,只需要更新数据源即可。

If (Not (ChangedRows) Is Nothing) Then

'打开连接。

Me.OleDbConnection1.Open()

'尝试更新数据源。

OleDbDataAdapter1.Update(ChangedRows)

End If

Catch updateException As System.Exception

'在此处添加错误处理代码。

Throw updateException

Finally

'无论是否引发了异常都关闭连接。

Me.OleDbConnection1.Close()

End Try

End Sub

Public Sub FillDataSet(ByVal dataSet As DS)

'在填充数据集前关闭约束检查。

'这允许适配器填充数据集而不用考虑

'表之间的依赖项。

dataSet.EnforceConstraints = False

Try

'打开连接。

Me.OleDbConnection1.Open()

'尝试通过 OleDbDataAdapter1 填充数据集。

Me.OleDbDataAdapter1.Fill(dataSet)

Catch fillException As System.Exception

'在此处添加错误处理代码。

Throw fillException

Finally

'重新打开约束检查。

dataSet.EnforceConstraints = True

'无论是否引发了异常都关闭连接。

Me.OleDbConnection1.Close()

End Try

End Sub

Private Sub row_changing(ByVal sender As Object, ByVal e As DS.authorsRowChangeEvent)

'对新增加行进行数值验证

If e.Action = DataRowAction.Add Then

'此处为了简单,以字段au_id不能为""为例

If editau_id.Text = "" Then

Throw (New Exception("数据不能为空"))

End If

End If

'还可以对记录的编辑值进行验证

'If e.Action = DataRowAction.Change Then

'此处填入编辑验证代码

'End If

'其它验证,依照上面加入吧

End Sub

End Class

以上代码在Microsoft Visual Studio .NET 2003 + SQL Server 2000中的“pubs” 示例数据库中调试通过。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有