Introduction
First of all, this article is totally for beginners. So there is no special thing for intermediate and advanced level programmers.
This article demonstrates how we can design forms in .NET applications, apply appropriate validation (field level and form level) on controls and use some functions to perform database operations.
These are some tips for commonly faced problems by beginners in .NET. Some of these tips are mine and some of these I have got from different sources. My aim is not to claim the ownership of these tips, but as a newcomer I faced these problems and had to do lot of Googling. So just to help my fellow programmers, I am putting this together.
Background
I have 2.5 years experience in .NET. My primary role is to guide (or handle) my subordinate and new programmers during development of desktop applications. During this, I feel that many newcomers make common mistakes like writing separate code for validation for each control, creating database connection objects (Connection
, DataSet
, DataAdapter
, etc.) on each form or even in each procedure, placing controls anywhere in the form, etc. So I thought of sharing this knowledge with other newcomers that are not in my company.
Content
This article contains the following three issues:
- Form Level Validation Function
- Database Related Function
- User Interface Related Tips
For all types of validation, I create a module (mdcheking
) which holds some public
variables and functions. First of all, we declare some public
variables as follows:
Public msgboxTitle As String = "My Application Title"
Public MessageBoxMessage As String = "Can not leave mandatory field as blank"
Variable msgboxTitle
holds the title of the application and it is displayed in the title bar of the Message Box. Variable MessageBoxMessage
holds the message which we want to prompt to the user. It contains a fixed string which prompts the user to fill or select compulsory fields.
Now we discuss other functions (or procedures) one by one. This function is very simple but it is very useful for beginners.
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
The above function takes two arguments. The first argument MessageBoxMessage
contains the message which we want to display to the user. The second argument MessageBoxTitle
is optional. In some cases, we want to display some other title in the message box in place of the Application title. So in this case, we supply some value for the second argument otherwise there is no requirement to pass the second argument when we call this method.
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
In the above function, we check whether Text
property of supplied TextBox
is blank or not? If it is blank, then it prompts the user and sets focus to the appropriate field and returns True
otherwise it returns False
. It takes three arguments. In the first parameter st,
we supply a TextBox
as Byref
. The second and third parameters are optional. If the last two parameters are supplied, then the supplied message and title appear in the message box, otherwise it shows our application title and message which we already declared in the declaration section of the module.
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
In the above function, we check whether Text
property of supplied ComboBox
is blank or not? If it is blank, then it prompts the user and sets focus to the appropriate field and returns True
otherwise it returns False
. It takes three arguments. In the first parameter st,
we supply a ComboBox
as Byref
. The second and third parameters are optional. If the last two parameters are supplied, then the supplied message and title appear in the message box otherwise it shows our application title and message which we already declared in the declaration section of the module.
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
In the above function, we simply pass a key which is checked to see whether it is related to any alphabets (or within any control keys or white space or decimal sign or "&" sign) then it is allowed, otherwise it is rejected. This procedure does not allow any other character which is not in the above specified range. This procedure is generally used on Keypress
event of TextBox
.
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
In the above function, we simply pass a key which is checked to see whether it is related to any number (or within any control keys ), then it is allowed otherwise it is rejected. This procedure does not allow any other character which is not in the above specified range. This procedure is generally used on Keypress
event of TextBox
.
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
The above function is the same as CheckPressedKeyForNumericWithoutDot
except with one difference. It allows only single decimal symbol. The second parameter contains the original string which first checks whether it contains any decimal symbol or not? If it contains any decimal symbol, then Key is passed to CheckPressedKeyForNumericWithoutDot
which allows only numeric value and if the second parameter does not contain any decimal symbol, then it allows numeric value with decimal symbol.
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
The purpose of the above function is allow to only Telephonic character. It allows any digit, comma(,) and hyphen(-). If the supplied key is within these characters, then it is allowed, otherwise it is rejected.
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
At the beginner level, everyone is struggling when he/she wants to save an image into database (I am also facing this problem). So I want to say that first convert the image into byte array and store this byte array in the database. The above function converts the image into byte array.
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
When we retrieve image data from database, it is in raw format (byte). Simply convert this byte array into image and use it. The above function converts the byte array into an image.
There are also some common mistakes made by beginners. They create database related objects (like connection, Data Adapter, connection string, etc.) on each form (or sometimes in each procedure). So here I want to show that there is no requirement to use database related object (and namespace) on each form. We can create this object (and some function for access database) in class (or module. I prefer class.). For this article, I use MSAccess database. Since in the initial stage everyone prefers this simple database.
In the declaration section of class, we create some database related variables which are used mostly like connection object, connection string, etc.
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
contains the database provider and data source info. I think there are no requirements to describe all other variables since you can easily guess the role from their data type.
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
When we want only a single value from the database table, then we use the above 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
When we want to simply insert record or delete record or update record, then we use the above 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
Whenever we want to get multiple records, we use the above function. In the above function, I fill the records in Dataset
table, however you can directly fill the record in 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
The above function is also used when we want to insert or delete or update the record. This function is specially created to insert images in the database.
There are also some issues when we design the interface of Desktop application. I point out some of them one by one:
- Font name and size should be standard for complete application.
- If you use menu strip, then a window menu must reside there.
- Use separator in menu for group related fields.
- Make sensible caption text for error messages, labels and form titles.
- Use meaningful names for each control and form (not like
button1
,Textbox1
, form1
, etc.) - Use prefix for controls and forms (like
lbl
for Label
, txt
for TextBox
, cmb
for ComboBox
, frm
for Form
, etc.) - Use progressbar when any task takes too much time.
- Absolutely no spelling errors.
- Place red asterisk (or error provider) for mandatory fields.
- Sometimes two words carry different meanings with a slight change in spelling. Make sure you use the correct one (for example, Principle and Principal, Labor and Labour, etc.)
- If you are working for an International customer, then date should be in the right format.
- Colors should be easy to the eye and pleasing. No fancy colors unless you need to highlight something.
- Hot Keys should be defined for every possible option.
- Check anchoring for each and every control on form.
- Set dock for controls whenever required.
- Tab order should be proper (in sequence).
- Order of fields should be very relevant. (For example in
Employee
form, you should keep personal detail related fields in one group and official detail related fields in another group). - If you are using group box to categorize the fields, then they should be even space from left and right edge of form.
- If maximize is not required, then make form border as fixed single and disable maximize button.
- Individual forms should carry the same icon as that for menu item.
- Button height and width should be standard for complete application.
- If possible, Button location should be standard for complete application (for example, Close button location should be standard for each and every form)
Label
and their corresponding controls (TextBox
, ComboBox
, etc.) should be aligned with Vertical Center. - Gap between labels and their corresponding controls should be even for complete application.
- If possible, then set maximum length for
TextBox
. - Fields like
ComboBox
, CheckListBox
must be sorted. - If icons are being used, they look sensible and relative, not attractive.
- If you use
Datagridview
, then Column headers must be middle aligned. - If you bind the
Datagridview
, then column headers must have some relevant name (not the database field name). - In
Datagridview
, numeric field should be right aligned and rest of the fields should be left aligned. - If application is MDI, then any change in single form should reflect to all other related form if this form is open (for example, there are multiple forms open which are related to employee and you used
Employee
name and their father's name related field in each form and now if we change the Employee
name or father's name in main employee form, then this should be reflected in all other opened forms.)
History