65.9K
CodeProject 正在变化。 阅读更多。
Home

初学者创建第一个桌面应用程序的技巧

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.24/5 (22投票s)

2009年1月4日

CPOL

8分钟阅读

viewsIcon

46800

downloadIcon

1014

一篇面向初学者的文章, 介绍了如何应用窗体级别验证和一些常见的数据库函数

引言

首先,本文档完全面向初学者。因此,对于中级和高级程序员没有特别之处。

本文档演示了如何在 .NET 应用程序中设计窗体,对控件应用适当的验证(字段级别和窗体级别),并使用一些函数执行数据库操作。

这些是 .NET 初学者经常遇到的问题的一些技巧。其中一些技巧是我的,有些是我从不同来源获得的。我的目标不是声称拥有这些技巧的所有权,而是作为一个新手,我遇到了这些问题,不得不进行大量的谷歌搜索。所以,为了帮助我的同行程序员,我将它们整理在一起。

背景

我在 .NET 领域有 2.5 年的经验。我的主要职责是在开发桌面应用程序期间指导(或处理)我的下属和新程序员。在此过程中,我发现许多新手会犯一些常见的错误,例如为每个控件编写单独的验证代码,在每个窗体甚至每个过程中创建数据库连接对象(Connection, DataSet, DataAdapter 等),随意放置控件等。所以我想与公司外的新手分享这些知识。

Content

本文档包含以下三个主要问题

  1. 窗体级验证函数
  2. 数据库相关函数
  3. 用户界面相关技巧

窗体级验证函数

对于所有类型的验证,我创建一个模块(mdcheking),其中包含一些 public 变量和函数。首先,我们声明一些 public 变量如下

 Public msgboxTitle As String = "My Application Title"
 Public MessageBoxMessage As String = "Can not leave mandatory field as blank"

变量 msgboxTitle 保存应用程序的标题,它显示在消息框的标题栏中。变量 MessageBoxMessage 保存我们要提示用户的信息。它包含一个固定字符串,提示用户填写或选择必填字段。

现在我们逐一讨论其他函数(或过程)。这个函数非常简单,但对初学者非常有益。

Public Sub Prompt(ByVal MessageBoxMessage As String, _
	Optional ByVal MessageBoxTitle As String = Nothing)
 	If MessageBoxTitle = Nothing Then 
		MsgBox(MessageBoxMessage, MsgBoxStyle.Information, msgboxTitle)
 	Else
	 	MsgBox(MessageBoxMessage, MsgBoxStyle.Information, MessageBoxTitle)
 	End If
End Sub    

上面的函数接受两个参数。第一个参数 MessageBoxMessage 包含我们要显示给用户的信息。第二个参数 MessageBoxTitle 是可选的。在某些情况下,我们想在消息框中显示一个不同的标题,而不是应用程序的标题。所以,在这种情况下,我们为第二个参数提供一些值,否则在调用此方法时无需传递第二个参数。

Public Function IsBlankTextBox(ByRef st As TextBox, _
	Optional ByVal PromptMessage As String = Nothing,_
	Optional ByVal MessageBoxTitle As String = Nothing) As Boolean
        If st.Text.Trim = "" Then
            If PromptMessage = Nothing Then
                If MessageBoxTitle = Nothing Then
                    Prompt(MessageBoxMessage)
                Else
                    Prompt(MessageBoxMessage, MessageBoxTitle)
                End If
            Else
                If MessageBoxTitle = Nothing Then
                    Prompt(PromptMessage)
                Else
                    Prompt(PromptMessage, MessageBoxTitle)
                End If
            End If
            st.Focus()
            Return True
        Else
            Return False
        End If

 End Function

在上面的函数中,我们检查提供的 TextBoxText 属性是否为空?如果为空,它会提示用户并将焦点设置到相应的字段,并返回 True,否则返回 False。它接受三个参数。在第一个参数 st 中,我们以 Byref 的方式提供一个 TextBox。第二个和第三个参数是可选的。如果提供了最后两个参数,则在消息框中显示提供的消息和标题,否则显示我们的应用程序标题和我们在模块声明部分已声明的消息。

Public Function IsBlankComboBox(ByVal st As ComboBox, _
	Optional ByVal PromptMessage As String = Nothing,_
	Optional ByVal MessageBoxTitle As String = Nothing) As Boolean 
	 If st.Text.Trim = "" Then 
		If PromptMessage = Nothing Then 
			If MessageBoxTitle = Nothing Then 
				Prompt(MessageBoxMessage)
			Else 
				Prompt(MessageBoxMessage, MessageBoxTitle)
			End If
		Else
			If MessageBoxTitle = Nothing Then
				Prompt(PromptMessage)
			Else 
			 	Prompt(PromptMessage, MessageBoxTitle) 
			End If
	 	End If
	 	st.Focus()
	 	Return True
	 Else
	 	Return False
	 End If
 End Function

在上面的函数中,我们检查提供的 ComboBoxText 属性是否为空?如果为空,它会提示用户并将焦点设置到相应的字段,并返回 True,否则返回 False。它接受三个参数。在第一个参数 st 中,我们以 Byref 的方式提供一个 ComboBox。第二个和第三个参数是可选的。如果提供了最后两个参数,则在消息框中显示提供的消息和标题,否则显示我们在模块声明部分已声明的应用程序标题和消息。

Public Sub CheckPressedKeyForAlphabates_
	(ByVal key As System.Windows.Forms.KeyPressEventArgs)
        If Not (Char.IsControl(key.KeyChar) Or _
	Char.IsLetter(key.KeyChar) Or Char.IsWhiteSpace(key.KeyChar) _
	Or key.KeyChar = "." Or key.KeyChar = "&") Then
            key.Handled = True
        End If
 End Sub

在上面的函数中,我们只传递一个键,该键被检查是否与任何字母(或任何控件键、空格、小数点或“&”符号)相关,如果是则允许,否则拒绝。此过程不允许任何不在上述指定范围内的其他字符。此过程通常用于 TextBoxKeypress 事件。

Public Sub CheckPressedKeyForNumericWithoutDot_
	(ByVal key As System.Windows.Forms.KeyPressEventArgs)
        If Not (Char.IsControl(key.KeyChar) Or Char.IsNumber(key.KeyChar)) Then
            key.Handled = True
        End If
End Sub

在上面的函数中,我们只传递一个键,该键被检查是否与任何数字(或任何控件键)相关,如果是则允许,否则拒绝。此过程不允许任何不在上述指定范围内的其他字符。此过程通常用于 TextBoxKeypress 事件。

Public Sub CheckPressedKeyForNumericWithDot_
	(ByVal key As System.Windows.Forms.KeyPressEventArgs, ByVal str As String)
        If str.Contains(".") Then
            CheckPressedKeyForNumericWithoutDot(key)
        Else
            If Not (Char.IsControl(key.KeyChar) Or _
		Char.IsNumber(key.KeyChar) Or key.KeyChar = ".") Then
                key.Handled = True
            End If
        End If
 End Sub 

上面的函数与 CheckPressedKeyForNumericWithoutDot 相同,只是有一个区别。它只允许单个小数点符号。第二个参数包含原始字符串,首先检查它是否包含任何小数点符号?如果包含任何小数点符号,则将 Key 传递给 CheckPressedKeyForNumericWithoutDot,它只允许数字值;如果第二个参数不包含任何小数点符号,则它允许带小数点的数字值。

 Public Sub CheckPhoneNo(ByVal key As System.Windows.Forms.KeyPressEventArgs)
	If Not (Char.IsControl(key.KeyChar) Or Char.IsNumber(key.KeyChar) _
		Or key.KeyChar = "-" _
	Or key.KeyChar = ",") Then
     		key.Handled = True
	End If
 End Sub        

上面函数的目的是只允许输入电话号码字符。它允许任何数字、逗号 (,) 和连字符 (-)。如果提供的键属于这些字符,则允许,否则拒绝。

 Public Function imageToByteArray(ByVal ImageIn As System.Drawing.Image) As Byte()
        Dim ms As MemoryStream = New MemoryStream()
        Dim FormatImage1 As Imaging.ImageFormat = ImageIn.RawFormat
        ImageIn.Save(ms, FormatImage1)
        Return ms.ToArray()
 End Function        

在初学阶段,每个人在想将图像保存到数据库时都会遇到困难(我本人也遇到过这个问题)。所以,我想说首先将图像转换为字节数组,然后将该字节数组存储在数据库中。上面的函数将图像转换为字节数组。

 Public Function ByteArrayToimage(ByVal ImageArray As Byte()) As Image
        Dim ms As MemoryStream = New MemoryStream(ImageArray)
        Dim ReturnImage As Image = Image.FromStream(ms)
        Return ReturnImage
 End Function        

当我们从数据库检索图像数据时,它是原始格式(字节)。只需将此字节数组转换为图像即可使用。上面的函数将字节数组转换为图像。

数据库相关函数

初学者还会犯一些常见的错误。他们会在每个窗体(有时甚至在每个过程中)创建数据库相关的对象(如连接、数据适配器、连接字符串等)。所以在这里我想说明,没有必要在每个窗体上使用数据库相关的对象(和命名空间)。我们可以在类(或模块,我倾向于类)中创建这个对象(以及一些访问数据库的函数)。对于本文档,我使用的是 MSAccess 数据库。因为在初始阶段,每个人都倾向于使用这个简单的数据库。

在类的声明部分,我们创建一些常用的数据库相关变量,如连接对象、连接字符串等。

 Private ConnString As String = "Provider=Microsoft.jet.oledb.4.0;_
	data source=" & mdChecking.DatabasePath
 Private con As OleDbConnection
 Private com As OleDbCommand
 Private da As OleDbDataAdapter  

ConnString 包含数据库提供者和数据源信息。我认为不需要描述所有其他变量,因为你可以从它们的数据类型中轻松猜测出它们的作用。

 Public Function ReturnSingleValue(ByVal MyQuery As String) As Object
        Try
            con = New OleDbConnection(ConnString)
            com = New OleDbCommand(MyQuery, con)
            con.Open()
            Dim result As Object = com.ExecuteScalar
            con.Close()
            If IsDBNull(result) Then
                Return Nothing
            End If

            Return result
        Catch ex As Exception
            mdChecking.Prompt(ex.Message.ToString)
            If con.State = ConnectionState.Open Then
                con.Close()
            End If
        End Try
        Return Nothing
 End Function        

当我们只需要从数据库表中获取单个值时,我们就使用上面的函数。

 Public Function InsertDeleteUpdate(ByVal MyQuery As String) As Long
        Try
            con = New OleDbConnection(ConnString)
            com = New OleDbCommand(MyQuery, con)
            con.Open()
            Dim RowsAffected As Long
            RowsAffected = com.ExecuteNonQuery()
            con.Close()
            Return RowsAffected
        Catch ex As Exception
            mdChecking.Prompt(ex.Message.ToString)
            If con.State = ConnectionState.Open Then
                con.Close()
            End If
        End Try
        Return Nothing
 End Function  

当我们只需要插入记录、删除记录或更新记录时,我们就使用上面的函数。

 Public Function ReturnMultipleValue(ByVal MyQuery As String) As DataSet
        Dim ds As DataSet
	Try
            con = New OleDbConnection(ConnString)
            da = New OleDbDataAdapter(MyQuery, con)
            ds = New DataSet
            con.Open()
            da.Fill(ds)
            con.Close()
            Return ds
        Catch ex As Exception
            mdChecking.Prompt(ex.Message.ToString)
            If con.State = ConnectionState.Open Then
                con.Close()
            End If
        End Try
	Return ds
 End Function  

当我们想要获取多条记录时,我们就使用上面的函数。在上面的函数中,我将记录填充到 Dataset 表中,但是你也可以直接将记录填充到 DataTable 中。

 Public Sub ExecuteCommandQuery(ByVal comm As SqlCommand)
        Try
            con = New SqlConnection(ConnString)
            comm.Connection = con
            con.Open()
            comm.ExecuteNonQuery()
            con.Close()
        Catch ex As Exception
            mdChecking.Prompt(ex.Message.ToString)
            If con.State = ConnectionState.Open Then
                con.Close()
            End If
        End Try
 End Sub 

当我们需要插入、删除或更新记录时,也使用上面的函数。此函数专门用于将图像插入数据库。

用户界面相关技巧

在设计桌面应用程序界面时,也会出现一些问题。我一一指出

  1. 整个应用程序的字体名称和大小应保持标准。
  2. 如果你使用菜单栏,则必须有一个窗口菜单。
  3. 在菜单中使用分隔符对相关字段进行分组。
  4. 为错误消息、标签和窗体标题使用有意义的标题文本。
  5. 为每个控件和窗体使用有意义的名称(而不是像 button1Textbox1form1 等)。
  6. 为控件和窗体使用前缀(如 LabellblTextBoxtxtComboBoxcmbFormfrm 等)。
  7. 当任何任务耗时过长时,使用进度条。
  8. 绝对不要有拼写错误。
  9. 为必填字段放置红色星号(或错误提供者)。
  10. 有时两个词由于拼写稍有不同而具有不同的含义。确保你使用了正确的词(例如,Principle 和 Principal,Labor 和 Labour 等)。
  11. 如果你为国际客户工作,日期应采用正确的格式。
  12. 颜色应易于眼睛且令人愉悦。除非你需要突出显示某些内容,否则不要使用花哨的颜色。
  13. 应为所有可能的选项定义热键。
  14. 检查窗体上每个控件的锚定。
  15. 在需要时为控件设置停靠。
  16. 标签顺序应正确(按顺序)。
  17. 字段顺序应非常相关。(例如,在 Employee 窗体中,你应该将与个人详细信息相关的字段分组,将与官方详细信息相关的字段分组)。
  18. 如果你使用分组框来分类字段,那么它们与窗体的左右边缘的间距应相等。
  19. 如果不需要最大化,则将窗体边框设置为固定单边框并禁用最大化按钮。
  20. 单个窗体应带有与菜单项相同的图标。
  21. 整个应用程序的按钮高度和宽度应保持标准。
  22. 如果可能,按钮位置应在整个应用程序中保持标准(例如,关闭按钮的位置在每个窗体中都应保持标准)。
  23. Label 及其对应的控件(TextBoxComboBox 等)应垂直居中对齐。
  24. 整个应用程序中标签与其对应控件之间的间隙应保持均匀。
  25. 如果可能,为 TextBox 设置最大长度。
  26. ComboBoxCheckListBox 等字段必须排序。
  27. 如果使用了图标,它们看起来应该合理且相关,而不是吸引眼球。
  28. 如果你使用 Datagridview,则列标题必须居中对齐。
  29. 如果你绑定 Datagridview,则列标题应具有相关的名称(而不是数据库字段名)。
  30. Datagridview 中,数字字段应右对齐,其余字段应左对齐。
  31. 如果应用程序是 MDI 应用程序,那么单个窗体的任何更改都应反映到其他相关窗体(例如,有多个窗体打开与员工相关,并且你在每个窗体中使用了Employee姓名及其父亲姓名相关的字段,现在如果你在主员工窗体中更改Employee姓名或父亲姓名,那么这个更改应该反映到所有其他打开的窗体中)。

历史

  • 发布日期:2009 年 1 月 4 日
© . All rights reserved.