Click here to Skip to main content
Click here to Skip to main content
Go to top

Manage Data in a WinForms Application (without the Database)

, 6 Jun 2008
Rate this:
Please Sign up or sign in to vote.
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.
BirdWatch_VB

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 article might 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.

BirdWatcher
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.

BirdWatcher
Figure 2: Finding a Bird.


BirdWatcher
Figure 3: Listing All Birds.

Getting Started

There is a single solution included with this download, the solution contains a WinForms 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:

BirdWatcher
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
      • List All Birds
  • 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.

''' <span class="code-SummaryComment"><summary></span>
''' 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.
''' <span class="code-SummaryComment"></summary></span>
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"

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Exit the application
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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 exit the application, users will be presented with a message box which will ask them whether or not they wish to exit the application without saving. If users indicate 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.

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Exit the application
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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.

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Clear all form fields
    ''' <span class="code-SummaryComment"></summary></span>
    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 file, 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.

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Load the image into the picture box
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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 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.

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Create a new bird data file
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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.

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Open an existing bird data file
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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, 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.

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Open an existing bird data file
    ''' <span class="code-SummaryComment"></summary></span>
    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.

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Save the existing bird data file
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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.

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Save the existing bird data file with
    ''' a new file name
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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.

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Save the existing bird data file
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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.

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Set the current bird values to the form content
    ''' if the user navigates off the current bird, it will
    ''' save the content
    ''' <span class="code-SummaryComment"></summary></span>
    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"

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Add a new bird to the bird data list
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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.

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Remove the current bird from the bird
    ''' from the bird data list
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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.

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Find a specific bird
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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 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.

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Bird finder code
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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. Form2 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.

    ''' <span class="code-SummaryComment"><summary></span>
    ''' List all of the birds
    ''' in the bird data file
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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.

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Load the current bird into the form
    ''' <span class="code-SummaryComment"></summary></span>
    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"

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Navigate back to the previous record
    ''' if possible
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Navigate to the next bird
    ''' record if possible
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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"

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Dirty the form whenever the user
    ''' types into the bird name textbox
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    Private Sub txtBirdName_KeyPress(ByVal sender As System.Object, _
                                     ByVal e As
                                     System.Windows.Forms.KeyPressEventArgs) _
                                     Handles txtBirdName.KeyPress

        dirtyForm = True

    End Sub

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Dirty the form if the user clicks
    ''' on the gender combo box
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    Private Sub cboGender_MouseClick(ByVal sender As System.Object, _
                                     ByVal e As System.Windows.Forms.MouseEventArgs)
                                     Handles cboGender.MouseClick

        dirtyForm = True

    End Sub

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Dirty the form whenever the user
    ''' types into the bird location textbox
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    Private Sub txtLocation_KeyPress(ByVal sender As System.Object, _
                                     ByVal e As
                                     System.Windows.Forms.KeyPressEventArgs) _
                                     Handles txtLocation.KeyPress

        dirtyForm = True

    End Sub

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Dirty the form whenever the user
    ''' types into the bird name textbox
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    Private Sub txtBehavior_KeyPress(ByVal sender As System.Object, _
                                     ByVal e As
                                     System.Windows.Forms.KeyPressEventArgs) _
                                     Handles txtBehavior.KeyPress

        dirtyForm = True

    End Sub

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Dirty the form if the user
    ''' opens the dtp control
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    Private Sub dtpDate_CloseUp(ByVal sender As System.Object, _
                                ByVal e As System.EventArgs) _
                                Handles dtpDate.CloseUp

        dirtyForm = True

    End Sub

    ''' <span class="code-SummaryComment"><summary></span>
    ''' Dirty the form if the user
    ''' opens the dtp control
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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

''' <span class="code-SummaryComment"><summary></span>
''' 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.
''' <span class="code-SummaryComment"></summary></span>
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 listbox control used to display the bird names.

    ''' <span class="code-SummaryComment"><summary></span>
    ''' 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
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="bd"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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 listbox 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.

    ''' <span class="code-SummaryComment"><summary></span>
    ''' When the user clicks on the find button,
    ''' raise an event so the main form will display
    ''' the appropriate bird
    ''' <span class="code-SummaryComment"></summary></span>
    ''' <span class="code-SummaryComment"><param name="sender"></param></span>
    ''' <span class="code-SummaryComment"><param name="e"></param></span>
    ''' <span class="code-SummaryComment"><remarks></remarks></span>
    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.

''' <span class="code-SummaryComment"><summary></span>
''' 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
''' <span class="code-SummaryComment"></summary></span>
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 WinForms application without actually backing the application with a database. Such an approach might be useful in a number of different applications 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.

History

  • 3rd June, 2008: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

salysle
Software Developer (Senior)
United States United States
No Biography provided

Comments and Discussions

 
QuestionHow to password protect the final database file? PinmemberMember 870661314-Jul-12 18:50 
QuestionMy vote of 3 PinmemberMember 383949522-Mar-12 4:50 
GeneralSorting is missing PinmemberJunner200627-Apr-09 5:47 
GeneralSuggestion Pinmemberdnpro9-Jun-08 23:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140926.1 | Last Updated 6 Jun 2008
Article Copyright 2008 by salysle
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid