Introduction
This article provides
an approach to building an application that may be used to collect, store, and
retrieve data without relying upon a database to get there. If you need to
store a limited amount of data, if your users won't be sharing data with other
users, and you do not require a full blown relational database on the backend,
this might article be of interest.
The article is built
around a demonstration project that allows the user to store some information
gathered during bird observation; of course the same approach could be used to
work with contact information, an inventory, postage stamp collection, coin
collections, movie collections, or whatever else you might be interested in
keeping tabs on.
Figure 1: Application
Main Form
The application
provides the following functionality:
-
Create a bird data
file.
-
Add birds to the
bird data file.
-
Remove birds from
the bird data file.
-
Search for
specific birds by name.
-
Create and edit
details about the bird.
-
Bird name
-
Bird gender
-
Bird location
-
Bird behavior
-
Observation
date
-
Observation
time
-
Image of the
bird
-
Save a bird data
file.
-
Reopen a bird data
file.
-
Navigate through
all of the birds in the bird data file.
-
View a list of all
birds in the bird data file.
The approaches used within the application are
representative of only one way of doing things; as with most things in the .NET
world, there are several alternatives and you can modify the code to work with
the data using one of the other alternatives if you prefer to do so.
Figure 2: Finding a
Bird
Figure 3: Listing All
Birds
Getting Started
There is a single
solution included with this download, the solution contains a Win Forms project
called "BirdWatch_VB"; this project contains three forms (the main form, a
search form, and a form used to display the total list of birds), a serializable
class called 'BirdData.vb' (used to contain bird related data), and a class
entitled, 'FileSerializer.vb' which contains two static methods used to
serialize and deserialize the bird data (writing it to and reading it from a
file) .
If you open the
attached project into Visual Studio 2008; you should see the following in the
solution explorer:
Figure 4: Solution
Explorer
Code: BirdData.vb
The BirdData class is
the container class used to store all of the bird related data used in the
application. Whilst this demonstration uses bird data, this could easily be
replaced with something more useful to you.
The class begins with
the normal and default imports:
Imports System
Imports System.Drawing
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
The next section
contains the class declarations. Note that the class is declared as
serializable; the serializable attribute indicates that the class can be
serialized.
<Serializable()> _
Public Class BirdData
The region defined in
the class declares the member variables used internally by the class; any member
variables exposed externally are made accessible through public properties.
#Region "Member
Variables"
Private mId As System.Guid
Private mBirdName As String
Private mGender As String
Private mLocation As String
Private mBehaviorObserved As String
Private mDateViewed As DateTime
Private mTimeViewed As DateTime
Private mPicture As Byte()
Private mPictureName As String
#End Region
The next region of
code in the class contains the constructors. Two constructors are defined; a
default constructor that creates a new instance of the class and assigns it an
internal ID (as a Guid). The second constructor accepts a bird name as an
argument and, when called, this constructor generates both an ID and assigns the
bird name property to the bird name member variable.
#Region "Constructor"
Public Sub New()
mId
= Guid.NewGuid()
End Sub
Public Sub New(ByVal birdName)
mId
= Guid.NewGuid()
mBirdName
= birdName
End Sub
#End Region
The last bit of the
code in this class is contained within the properties region; this region
contains all of the properties defined to access the member variables. Note
that since the ID value is always set by the constructor, the property does not
provide a public interface to set the Guid to a new value.
#Region "Properties"
Public ReadOnly Property ID() As Guid
Get
Return mId
End Get
End Property
Public Property BirdName() As String
Get
Return mBirdName
End Get
Set(ByVal value As String)
mBirdName
= value
End Set
End Property
Public Property Gender() As String
Get
Return mGender
End Get
Set(ByVal value As String)
mGender
= value
End Set
End Property
Public Property Location() As String
Get
Return mLocation
End Get
Set(ByVal value As String)
mLocation
= value
End Set
End Property
Public Property BehaviorObserved() As String
Get
Return mBehaviorObserved
End Get
Set(ByVal value As String)
mBehaviorObserved
= value
End Set
End Property
Public Property DateViewed() As Date
Get
Return mDateViewed
End Get
Set(ByVal value As Date)
mDateViewed
= value
End Set
End Property
Public Property TimeViewed() As Date
Get
Return mTimeViewed
End Get
Set(ByVal value As Date)
mTimeViewed
= value
End Set
End Property
Public Property Picture() As Byte()
Get
Return mPicture
End Get
Set(ByVal value As Byte())
mPicture
= value
End Set
End Property
Public Property PictureName() As String
Get
Return mPictureName
End Get
Set(ByVal value As String)
mPictureName
= value
End Set
End Property
#End Region
End Class
That concludes the
description of the 'BirdData' class.
Code: Main Application Form (Form1.vb)
The Bird Tracker main
form contains the following controls:
-
Menu
-
File
-
New
-
Open
-
Save
-
Save As
-
Exit
-
View
-
Toolbar
-
Add Bird
-
Remove Bird
-
Find Bird
-
Save Bird Data
-
Navigate to
Previous Bird
-
Navigate to
Next Bird
-
Exit
Application
-
Bird name text box
control
-
Bird gender combo
box
-
Bird location
multiline text box
-
Bird Behavior
multiline text box
-
Date of
observation date time picker
-
Time of
observation date time picker
-
Group container
-
Picture box
-
Set Picture button
Figure 5: Form1.vb
The class begins with
the normal and default imports:
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Linq
Imports System.Text
Imports System.IO
Imports System.Windows.Forms
The next section
contains the class declaration.
''' <summary>
''' A simple project used to maintain data about a
''' collection of birds (could be anything), and to
''' display that data to the user, persist the data,
''' and allow the user to recover and modify the
''' data without using a database.
''' </summary>
Public Class Form1
The region defined in
the class declares the member variables used internally by the class; any member
variables exposed externally are made accessible through public properties. The
comment adjacent to each declaration describes its purpose.
#Region "Variable
Declarations"
Private birds As List(Of BirdData) '
a container for the bird collection
Private currentBird As BirdData '
the current bird (displayed)
Private currentFilePath As String '
the path to the bird data file
Private currentPosition As Integer '
the position within the bird list
Private dirtyForm As Boolean '
mark the form dirty when changed
#End Region
The next region of
code in the class contains the constructor. Upon initialization, the
application creates a new bird data list, creates a new bird data object, sets
the date and time picker controls to the current data, sets the current position
indicator to zero, and sets the dirty form Boolean to false.
#Region "Constructor"
Private Sub Form1_Load(ByVal sender As System.Object,
_
ByVal e As System.EventArgs) Handles MyBase.Load
'
create new bird data list
'
ready to write data
birds
= New List(Of BirdData)()
currentBird
= New BirdData()
birds.Add(currentBird)
'
set the date time pickers to now
dtpDate.Value
= DateTime.Now
dtpTime.Value
= DateTime.Now
'
init current position to zero
currentPosition
= 0
'
mark form as not dirty
dirtyForm
= False
End Sub
#End Region
The next code region
is called 'Housekeeping'. This region contains some basic functionality used to
operate the application. The first code section is for the Exit toolbar button
click event handler; this function merely calls the exit menu item option's
event handler rather than duplicate the code in both functions.
#Region "Housekeeping"
''' <summary>
'''
Exit the application
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub exitToolStripMenuItem_Click(ByVal sender As System.Object,
_
ByVal e As System.EventArgs)
_
Handles exitToolStripMenuItem.Click
If dirtyForm
= True Then
If MessageBox.Show(Me, "You
have not saved the current bird data; " +
_
"would
you like to save before exiting?", _
"Save
Current Data", MessageBoxButtons.YesNo) = _
System.Windows.Forms.DialogResult.Yes Then
saveToolStripMenuItem_Click(Me, New EventArgs())
End If
Else
Application.Exit()
End If
End Sub
The next section of
code is the exit menu option's click event handler. This code first checks to
see if the form is marked as dirty (based upon user changes made during the
operation of the application); if the form is dirty and the user attempts to
exist the application, the user will be presented with a message box which will
ask them whether or not they wish to exit the application without saving. If
the user indicates that they would prefer to save prior to exiting the
application, the application will present the save file dialog to the user;
otherwise the application will exit.
''' <summary>
'''
Exit the application
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub tsbExit_Click(ByVal sender As System.Object,
_
ByVal e As System.EventArgs) Handles tsbExit.Click
'
call the menu function
exitToolStripMenuItem_Click(Me, New EventArgs())
End Sub
The next method is
used to clear out all of the information displayed in the main form controls.
''' <summary>
'''
Clear all form fields
''' </summary>
Public Sub ClearForm()
dirtyForm
= True
txtBirdName.Text
= String.Empty
txtLocation.Text
= String.Empty
txtBehavior.Text
= String.Empty
cboGender.SelectedIndex
= -1
dtpDate.Value
= DateTime.Now
dtpTime.Value
= DateTime.Now
picBird.Image
= Nothing
End Sub
The next function
contained in the form is used to set the image associated with the current
bird. Since we are adding new data to the current instance of bird data, the
form is marked as dirty - this will allow the functions used to exit the
application to check to see if the current data needs to be saved prior to
exiting the application. The function uses the open file dialog to allow the
user to set a path to an image file; once a file path is set; the function
opens the files, converts it into a byte array and stores it in the current
bird data object's image property. The function wraps up by setting the form's
image to display selected bird picture.
''' <summary>
'''
Load the image into the picture box
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub btnSetImage_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnSetImage.Click
dirtyForm
= True
Dim imageFilePath As String = String.Empty
Dim OpenFileDialog1 As New OpenFileDialog()
OpenFileDialog1.Title
= "Open
Image File"
OpenFileDialog1.Filter
= "JPEG
Documents (*.jpg)|*.jpg|Gif Files|*.gif"
If OpenFileDialog1.ShowDialog()
= System.Windows.Forms.DialogResult.Cancel
Then
Return
End If
imageFilePath
= OpenFileDialog1.FileName
If String.IsNullOrEmpty(imageFilePath) Then
Return
End If
If System.IO.File.Exists(imageFilePath)
= False Then
Return
End If
Try
'
convert Image to byte array and save in
Dim fsImage As System.IO.FileStream
= Nothing
fsImage
= System.IO.File.Open(imageFilePath, FileMode.Open,
FileAccess.Read)
Dim bArrImage(fsImage.Length) As Byte
fsImage.Read(bArrImage,
0, Convert.ToInt32(fsImage.Length))
fsImage.Close()
currentBird.Picture
= bArrImage
currentBird.PictureName
= imageFilePath
Dim ms As New MemoryStream(bArrImage)
picBird.Image
= Image.FromStream(ms)
ms.Dispose()
Catch ex As Exception
MessageBox.Show(ex.Message, "Error
Storing Image")
End Try
End Sub
The next function up
is used to handle the 'New' menu option's click event; this function begins by
checking the dirty form Boolean to see if the current data should be saved prior
to starting the new bird data file. If the current form is dirty; the user will
be prompted to save the current data, else, a new collection of bird data is
created and the form is cleared all of prior entries.
''' <summary>
'''
Create a new bird data file
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub newToolStripMenuItem_Click(ByVal sender As System.Object,
_
ByVal e As System.EventArgs)
_
Handles newToolStripMenuItem.Click
If dirtyForm
= True Then
If (MessageBox.Show(Me, "You
have not saved the current bird data; " +
_
"would
you like to save before starting a new " +
_
"bird
database?", "Save
Current Data", _
MessageBoxButtons.YesNo)
= _
System.Windows.Forms.DialogResult.Yes) Then
saveToolStripMenuItem_Click(Me, New EventArgs())
Else
'
discard and start new document
birds
= New List(Of BirdData)()
ClearForm()
End If
Else
'
start new document
birds
= New List(Of BirdData)()
ClearForm()
End If
End Sub
The open file menu
option's click event handler is next; this function also checks for a dirty form
prior to opening a new bird data file into the application. If the form is not
dirty, the application will call the 'Open' function which will in turn allow
the user to navigate to and open a file for viewing or edit.
''' <summary>
'''
Open an existing bird data file
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub openStripMenuItem2_Click(ByVal sender As System.Object,
_
ByVal e As System.EventArgs)
_
Handles openStripMenuItem2.Click
If dirtyForm
= True Then
If (MessageBox.Show(Me, "You
have not saved the current bird data; " +
_
"would
you like to save before opening a different " +
_
"bird
database?", "Save
Current Data", _
MessageBoxButtons.YesNo)
= _
System.Windows.Forms.DialogResult.Yes) Then
saveToolStripMenuItem_Click(Me, New EventArgs())
Else
Open()
End If
Else
Open()
End If
End Sub
Next up, the open
method uses the open file dialog control to allow the user to navigate to and
select a bird data file. Once selected, the file is deserialized into the local
bird collection and made available to the display.
''' <summary>
'''
Open an existing bird data file
''' </summary>
Public Sub Open()
Dim OpenFileDialog1 As New OpenFileDialog()
OpenFileDialog1.Title
= "Open
BRD Document"
OpenFileDialog1.Filter
= "BRD
Documents (*.brd)|*.brd"
If OpenFileDialog1.ShowDialog()
= _
System.Windows.Forms.DialogResult.Cancel Then
Return
End If
currentFilePath
= OpenFileDialog1.FileName
If String.IsNullOrEmpty(currentFilePath) Then
Return
End If
If System.IO.File.Exists(currentFilePath)
= False Then
Return
End If
birds
= FileSerializer.Deserialize(currentFilePath)
'
Load bird at position zero
If birds.Count
<> 0 Then
currentBird
= birds.ElementAt(0)
LoadCurrentBird()
dirtyForm
= False
End If
End Sub
The save menu option
click event handler is up next. This function uses the save file dialog to
allow the user to name or set the path to the file. Once the file path is set,
the application serializes the data contained in the bird collection, saving it
to disk.
''' <summary>
'''
Save the existing bird data file
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub saveToolStripMenuItem_Click(ByVal sender As System.Object,
_
ByVal e As System.EventArgs)
_
Handles saveToolStripMenuItem.Click
SaveCurrentBird()
If String.IsNullOrEmpty(currentFilePath) Then
Dim SaveFileDialog1 As New SaveFileDialog()
Try
SaveFileDialog1.Title
= "Save
BRD Document"
SaveFileDialog1.Filter
= "BRD
Documents (*.brd)|*.brd"
If SaveFileDialog1.ShowDialog()
= _
System.Windows.Forms.DialogResult.Cancel Then
Return
End If
Catch
Return
End Try
currentFilePath
= SaveFileDialog1.FileName
End If
If String.IsNullOrEmpty(currentFilePath) Then
MessageBox.Show("File
path is not set.", "Save
Error")
Return
End If
FileSerializer.Serialize(currentFilePath,
birds)
MessageBox.Show("File
" + currentFilePath + "
saved.", "File
Saved")
dirtyForm
= False
End Sub
The next bit of code
is very similar to save; it allows the user to save the current bird data file
to the local hardware using a replacement name.
''' <summary>
'''
Save the existing bird data file with
'''
a new file name
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub saveAsToolStripMenuItem_Click(ByVal sender As System.Object,
_
ByVal e As System.EventArgs)
_
Handles saveAsToolStripMenuItem.Click
Dim SaveFileDialog1 As New SaveFileDialog()
Try
SaveFileDialog1.Title
= "Save
BRD Document"
SaveFileDialog1.Filter
= "BRD
Documents (*.brd)|*.brd"
If SaveFileDialog1.ShowDialog()
= _
System.Windows.Forms.DialogResult.Cancel Then
Return
End If
Catch
Return
End Try
currentFilePath
= SaveFileDialog1.FileName
If String.IsNullOrEmpty(currentFilePath) Then
Return
End If
FileSerializer.Serialize(currentFilePath,
birds)
MessageBox.Show("File
" + currentFilePath + "
saved.", "File
Saved.")
dirtyForm
= False
End Sub
The toolbar's save
button is up next; it merely calls the save menu item click event to save the
bird data file.
''' <summary>
'''
Save the existing bird data file
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub tsbSave_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles tsbSave.Click
saveToolStripMenuItem_Click(Me, New EventArgs())
End Sub
The save current bird
function is used to set the values of the current bird data object to match the
content from the form controls.
''' <summary>
'''
Set the current bird values to the form content
'''
if the user navigates off the current bird, it will
'''
save the content
''' </summary>
Private Sub SaveCurrentBird()
If Not String.IsNullOrEmpty(txtBirdName.Text) Then
Try
currentBird.BirdName
= txtBirdName.Text
currentBird.Location
= txtLocation.Text
currentBird.BehaviorObserved
= txtBehavior.Text
currentBird.Gender
= cboGender.Text
currentBird.DateViewed
= dtpDate.Value
currentBird.TimeViewed
= dtpTime.Value
'
bird image byte array is set for current
'
bird when image is set
Catch ex As Exception
MessageBox.Show(ex.Message, "Error")
End Try
End If
End Sub
#End Region
The next region is
called Bird Data Management; within this section are the methods used to manage
the bird data and the bird data collection. The first function contained in
this region is used to add a new bird to the collection. The function saves the
current bird, creates a new empty bird object, adds the new bird data object to
the birds collection, and then marks the form as dirty.
#Region "Bird
Data Management"
''' <summary>
'''
Add a new bird to the bird data list
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub tsbAdd_Click(ByVal sender As System.Object,
_
ByVal e As System.EventArgs)
_
Handles tsbAdd.Click
SaveCurrentBird()
currentBird
= New BirdData()
ClearForm()
birds.Add(currentBird)
dirtyForm
= True
End Sub
The next function is
used to remove a bird from the collection. After a bird is removed; the current
position is updated and the form reloaded with the replacement bird information.
''' <summary>
'''
Remove the current bird from the bird
'''
from the bird data list
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub tsbRemoveBird_Click(ByVal sender As System.Object,
_
ByVal e As System.EventArgs)
_
Handles tsbRemoveBird.Click
birds.RemoveAt(currentPosition)
If currentPosition
= 0 Then
currentPosition
+= 1
Else
currentPosition
-= 1
currentBird
= birds(currentPosition)
LoadCurrentBird()
dirtyForm
= True
End If
End Sub
The next function is
used to support finding a specific bird. When the click event handler is
executed, a new instance of the find form (Form3) is created and an event
handler for the find form's 'BirdNameUpdated' event is set.
''' <summary>
'''
Find a specific bird
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub tsbFindBird_Click(ByVal sender As System.Object,
_
ByVal e As System.EventArgs)
_
Handles tsbFindBird.Click
Dim f As New Form3(birds)
AddHandler f.BirdNameUpdated, AddressOf FindBird
f.Show()
End Sub
The next function up
is used to find a specific bird by its name. When find form raises the event
indicating that the user wants the bird of a particular name found in the
collection, this function will iterate through the collection until the match is
found and then it will make that bird the current bird and update the form to
display that bird's information.
''' <summary>
'''
Bird finder code
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub FindBird(ByVal sender As Object,
_
ByVal e As BirdNameUpdateEventArgs)
Dim i As Integer
For i
= 0 To birds.Count
- 1
If birds(i).BirdName
= e.BirdName Then
currentBird
= birds(i)
LoadCurrentBird()
currentPosition
= i
End If
Next
End Sub
The next function is
used to display a form containing all of the birds contained in the current bird
data list. Form 2 contains a single data grid view control and it accepts a
list of bird data as an argument for the constructor. When the form is created
and passed a copy of the current bird data, that data is bound to the data grid
view control and displayed to the user.
''' <summary>
'''
List all of the birds
'''
in the bird data file
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub listAllBirdsToolStripMenuItem_Click(ByVal sender As System.Object,
_
ByVal e As System.EventArgs)
_
Handles
listAllBirdsToolStripMenuItem.Click
Dim f As New Form2(birds)
f.Show()
End Sub
The next function is
called whenever the current bird is changed. It reloads all of the form
controls from the current bird object.
''' <summary>
'''
Load the current bird into the form
''' </summary>
Private Sub LoadCurrentBird()
Try
txtBirdName.Text
= currentBird.BirdName
txtLocation.Text
= currentBird.Location
txtBehavior.Text
= currentBird.BehaviorObserved
Catch
End Try
Try
cboGender.Text
= currentBird.Gender
Catch
End Try
Try
dtpDate.Value
= currentBird.DateViewed
Catch
End Try
Try
dtpTime.Value
= currentBird.TimeViewed
Catch
End Try
Try
If currentBird.Picture IsNot Nothing Then
Dim ms As New MemoryStream(currentBird.Picture)
picBird.Image
= Image.FromStream(ms)
ms.Dispose()
Else
picBird.Image
= Nothing
End If
Catch
picBird.Image
= Nothing
End Try
End Sub
#End Region
The next region
contained within this class contains two functions used to control navigation
forwards and backwards through the bird data list. In either case, the current
bird is saved by calling the 'SaveCurrentBird' function. After the current bird
is saved locally, the position is checked to see if it is at the bottom or top
limit and if possible, the position is incremented or decremented. Once the
current position is updated, the current bird data is set to the bird data at
the updated position and for the form reloaded.
#Region "Navigation"
''' <summary>
'''
Navigate back to the previous record
'''
if possible
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub tsbNavBack_Click(ByVal sender As System.Object,
_
ByVal e As System.EventArgs)
_
Handles tsbNavBack.Click
SaveCurrentBird()
If currentPosition
<> 0 Then
currentPosition
-= 1
currentBird
= birds(currentPosition)
LoadCurrentBird()
End If
End Sub
''' <summary>
'''
Navigate to the next bird
'''
record if possible
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub tsbNavForward_Click(ByVal sender As System.Object,
_
ByVal e As System.EventArgs)
_
Handles tsbNavForward.Click
SaveCurrentBird()
If currentPosition
< (birds.Count - 1) Then
currentPosition
+= 1
currentBird
= birds(currentPosition)
LoadCurrentBird()
End If
End Sub
#End Region
The last region of
code in this class is used to mark the form as dirty in response to changes.
Note that, rather than using the value changed events to set the form dirty,
other events such as the text box control's key press event were used to provide
an indication as to whether or not something was changed. The reason being
that, if one were to open a bird data file and navigate through the list, the
values would change and the form would be marked as dirty even though in reality
no changes took place.
#Region "Dirty
Form"
''' <summary>
'''
Dirty the form whenever the user
'''
types into the bird name textbox
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub txtBirdName_KeyPress(ByVal sender As System.Object,
_
ByVal e As
System.Windows.Forms.KeyPressEventArgs)
_
Handles txtBirdName.KeyPress
dirtyForm
= True
End Sub
''' <summary>
'''
Dirty the form if the user clicks
'''
on the gender combo box
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub cboGender_MouseClick(ByVal sender As System.Object,
_
ByVal e As System.Windows.Forms.MouseEventArgs)
Handles cboGender.MouseClick
dirtyForm
= True
End Sub
''' <summary>
'''
Dirty the form whenever the user
'''
types into the bird location textbox
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub txtLocation_KeyPress(ByVal sender As System.Object,
_
ByVal e As
System.Windows.Forms.KeyPressEventArgs)
_
Handles txtLocation.KeyPress
dirtyForm
= True
End Sub
''' <summary>
'''
Dirty the form whenever the user
'''
types into the bird name textbox
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub txtBehavior_KeyPress(ByVal sender As System.Object,
_
ByVal e As
System.Windows.Forms.KeyPressEventArgs)
_
Handles txtBehavior.KeyPress
dirtyForm
= True
End Sub
''' <summary>
'''
Dirty the form if the user
'''
opens the dtp control
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub dtpDate_CloseUp(ByVal sender As System.Object,
_
ByVal e As System.EventArgs)
_
Handles dtpDate.CloseUp
dirtyForm
= True
End Sub
''' <summary>
'''
Dirty the form if the user
'''
opens the dtp control
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub dtpTime_CloseUp(ByVal sender As System.Object,
_
ByVal e As System.EventArgs)
_
Handles dtpTime.CloseUp
dirtyForm
= True
End Sub
#End Region
End Class
That wraps up the
discussion of the code contained in the main form of the application.
Code: List All Birds Form (Form2.vb)
The form used to
display the entire list of birds contained in the current bird data list is
pretty simple. The form contains a single data grid view control which is used
to display the bird data list. The constructor was modified to accept a bird
data list as an argument; the constructor binds the data grid view control to
the bird data list and hides the first column (containing a Guid used to
uniquely identify the record).
The code for this
class is provided in total:
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Linq
Imports System.Text
Imports System.Windows.Forms
Public Class Form2
Public Sub New(ByVal bd As List(Of BirdData))
InitializeComponent()
'
set the datasource of the grid
dataGridView1.DataSource
= bd
'
this is a guid to hide it
dataGridView1.Columns(0).Visible
= False
End Sub
End Class
That concludes the
description of the 'Form2' class.
Code: Find Birds Form (Form3.vb)
This form is used to
provide the user with a list of the names of all of the birds contained in the
current bird data list. The user can view and select bird names from the list
and then click on the form's Find button; this will raise an event which will be
used by the main form to load the matching bird into the form.
The class begins with
the normal and default library imports, namespace declaration, and class
declaration:
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Linq
Imports System.Text
Imports System.Windows.Forms
''' <summary>
''' This form class displays a list of existing
''' bird names for the user to pick from; once
''' selected, an event will be raised with
''' the selected bird name passed as an
''' argument. The
main form will listen
''' for an process this event to update
''' the display of the current bird to match
''' the search bird.
''' </summary>
Public Class Form3
Following the class
declaration, a delegate and event are declared; these are used to notify the
main form whenever the user selects a bird from the form's list and then clicks
the form's Find button. The 'BirdNameUpdateEventArgs' is declared as a separate
class; that class will be used to contain the selected bird name and to make
that information available to the main form whenever the event is raised.
'
add a delegate
Public Delegate Sub BirdNameUpdateHandler(ByVal sender As Object, ByVal e As
BirdNameUpdateEventArgs)
'
and associated event to notify
'
listeners when a bird name is
'
picked from this form's bird
'
name list
Public Event BirdNameUpdated As BirdNameUpdateHandler
The constructor was
modified to accept a bird data list as an argument; whenever an instance of the
form is created, the constructor will iterate through the bird data list and add
each bird name to the list box control used to display the bird names.
''' <summary>
'''
Pass current bird data list to the
'''
constructor so that the form can
'''
generate a list of bird names for
'''
the user to choose from
''' </summary>
''' <param
name="bd"></param>
''' <remarks></remarks>
Public Sub New(ByVal bd As List(Of BirdData))
InitializeComponent()
'
iterate the bird data to add
'
each bird name to the bird
'
name list box control
For Each bird As BirdData In bd
listBox1.Items.Add(bird.BirdName)
Next
End Sub
The find button click
event handler creates an instance of the event arguments and adds the list box
control's selected item to the event arguments. Once set, the event is raised
and raising the event will force the main form to load the selected bird's
information into the form's controls.
''' <summary>
'''
When the user clicks on the find button,
'''
raise an event so the main form will display
'''
the appropriate bird
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub btnFind_Click(ByVal sender As System.Object,
_
ByVal e As System.EventArgs)
_
Handles btnFind.Click
'
populate the argument list with the bird name
Dim args As New BirdNameUpdateEventArgs(listBox1.SelectedItem.ToString())
'
raise the event to pass the bird name back to the
'
main form for processing
RaiseEvent BirdNameUpdated(Me,
args)
End Sub
The
'BirdNameUpdateEventArgs' class is used to contain the bird name and to
facilitate passing the bird name to the main form whenever the bird name updated
event is fired. This class could be expanded to contain greater numbers of
properties.
''' <summary>
''' Container for the bird name update event arguments;
''' in this case there is only one argument, that being
''' the selected name of a bird from the bird list
''' </summary>
Public Class BirdNameUpdateEventArgs
Inherits System.EventArgs
Private mBirdName As String
'
Class constructor
Public Sub New(ByVal sBirdName As String)
Me.mBirdName
= sBirdName
End Sub
'
Properties - Accessible by the listener
Public Property BirdName() As String
Get
Return mBirdName
End Get
Set(ByVal value As String)
mBirdName
= value
End Set
End Property
End Class
That wraps up the
discussion of the find form class (Form3.vb).
Summary
The article shows one
approach that may be used to persist and manage data within a win forms
application without actually backing the application with a database. Such an
approach might be useful in a number of different applications and where the
user does not share information with other users. Even though the example shows
the approach used to manage a collection of information regarding birds, it
could be used for any number of other purposes such as maintaining a library of
fly patterns, or your favorite insect collection, inventories of tools or
equipment, etc.