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

在 WinForms 应用程序中管理数据(无需数据库)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.29/5 (6投票s)

2008年6月6日

CPOL

12分钟阅读

viewsIcon

55083

downloadIcon

2423

本文提供了一种构建应用程序的方法,该应用程序可在不依赖数据库的情况下收集、存储和检索数据。

BirdWatch_VB

引言

本文提供了一种构建应用程序的方法,该应用程序可在不依赖数据库的情况下收集、存储和检索数据。如果您需要存储少量数据,您的用户将不会与其他用户共享数据,并且您不需要后端有一个功能完善的关系数据库,那么本文可能会引起您的兴趣。

本文围绕一个演示项目构建,该项目允许用户存储在鸟类观察期间收集的一些信息;当然,相同的方法也可以用于处理联系人信息、库存、邮票收藏、硬币收藏、电影收藏,或者您想跟踪的任何其他内容。

BirdWatcher
图 1:应用程序主窗体。

该应用程序提供以下功能:

  • 创建鸟类数据文件。
  • 将鸟类添加到鸟类数据文件中。
  • 从鸟类数据文件中删除鸟类。
  • 按名称搜索特定鸟类。
  • 创建和编辑鸟类详细信息。
    • 鸟名
    • 鸟的性别
    • 鸟类地点
    • 鸟类行为
    • 观察日期
    • 观察时间
    • 鸟的照片
  • 保存鸟类数据文件。
  • 重新打开鸟类数据文件。
  • 浏览鸟类数据文件中的所有鸟类。
  • 查看鸟类数据文件中的所有鸟类列表。

应用程序中使用的方法仅代表一种做事方式。与 .NET 世界中的大多数事物一样,有几种替代方案,如果您愿意,可以修改代码以使用其他替代方案之一来处理数据。

BirdWatcher
图 2:查找鸟类。


BirdWatcher
图 3:列出所有鸟类。

入门

下载中包含一个解决方案,该解决方案包含一个名为 BirdWatch_VB 的 WinForms 项目;该项目包含三个窗体(主窗体、搜索窗体和用于显示鸟类总列表的窗体)、一个名为 BirdData.vb 的可序列化类(用于包含鸟类相关数据),以及一个名为 FileSerializer.vb 的类,其中包含两个 static 方法,用于将鸟类数据序列化和反序列化(写入和读取文件)。

如果您在 Visual Studio 2008 中打开附加的项目;您应该会在解决方案资源管理器中看到以下内容:

BirdWatcher
图 4:解决方案资源管理器。

代码:BirdData.vb

BirdData 类是用于存储应用程序中所有鸟类相关数据的容器类。虽然此演示使用鸟类数据,但可以轻松地将其替换为您更有用的内容。

该类以常规的默认 imports 开始

Imports System
Imports System.Drawing
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text

下一部分包含类声明。请注意,该类声明为 serializableserializable 属性表示该类可以被序列化。

<Serializable()> _
Public Class BirdData

类中定义的区域声明了类内部使用的成员变量;所有对外公开的成员变量都通过 public 属性进行访问。

#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

类中的下一段代码包含构造函数。定义了两个构造函数;一个默认构造函数,它创建一个类的新实例并为其分配一个内部 ID(作为 Guid)。第二个构造函数接受一个鸟名作为参数,在调用时,此构造函数会生成一个 ID 并将鸟名属性分配给鸟名成员变量。

#Region "Constructor"

    Public Sub New()

        mId = Guid.NewGuid()

    End Sub

    Public Sub New(ByVal birdName)

        mId = Guid.NewGuid()
        mBirdName = birdName

    End Sub

#End Region

此类代码的最后一部分包含在 properties 区域中;该区域包含所有用于访问成员变量的 properties 。请注意,由于 ID 值始终由构造函数设置,因此该属性不提供 public 接口来将 Guid 设置为新值。

#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

以上是 BirdData 类的说明。

代码:主应用程序窗体 (Form1.vb)

鸟类追踪器主窗体包含以下控件:

  • Menu
    • 文件
      • 新建
      • 打开
      • 保存
      • 另存为
      • 退出
    • 视图
      • 列出所有鸟类
  • 工具栏
    • 添加鸟类
    • 删除鸟类
    • 查找鸟类
    • 保存鸟类数据
    • 导航到上一只鸟
    • 导航到下一只鸟
    • 退出应用程序
  • 鸟名文本框控件
  • 鸟的性别组合框
  • 鸟类地点多行文本框
  • 鸟类行为多行文本框
  • 观察日期日期时间选择器
  • 观察时间日期时间选择器
  • 组容器
  • 图片框
  • 设置图片按钮


图 5:Form1.vb。

该类以常规的默认 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

下一部分包含类声明。

''' <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

类中定义的区域声明了类内部使用的成员变量;所有对外公开的成员变量都通过 public 属性进行访问。每个声明旁边的注释描述了它的用途。

#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

类中的下一段代码包含构造函数。在初始化时,应用程序会创建一个新的鸟类数据列表,创建一个新的鸟类数据对象,将日期和时间选择器控件设置为当前日期,将当前位置指示器设置为零,并将脏窗体 Boolean 设置为 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

下一个代码区域称为 Housekeeping。此区域包含用于操作应用程序的一些基本功能。第一个代码部分是用于退出工具栏按钮的点击事件处理程序;此函数仅调用退出菜单项选项的事件处理程序,而不是在两个函数中复制代码。

#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

下一个代码部分是退出菜单选项的点击事件处理程序。此代码首先检查窗体是否被标记为脏(基于用户在应用程序运行期间所做的更改);如果窗体是脏的,并且用户尝试退出应用程序,将向用户显示一个消息框,询问他们是否希望在不保存的情况下退出应用程序。如果用户表示他们希望在退出应用程序之前保存,应用程序将向用户显示保存文件对话框;否则,应用程序将退出。

    ''' <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

下一个方法用于清除主窗体控件中显示的所有信息。

    ''' <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

窗体中包含的下一个函数用于设置与当前鸟类关联的图像。由于我们正在向当前鸟类数据实例添加新数据,因此窗体被标记为脏——这将允许用于退出应用程序的函数检查当前数据是否需要在退出应用程序之前保存。该函数使用打开文件对话框允许用户设置图像文件的路径;一旦设置了文件路径;该函数打开文件,将其转换为字节数组,并将其存储在当前鸟类数据对象的图像属性中。该函数最后设置窗体的图像以显示选定的鸟类图片。

    ''' <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

下一个函数用于处理“新建”菜单选项的点击事件;此函数首先检查脏窗体 Boolean ,以查看是否应在开始新的鸟类数据文件之前保存当前数据。如果当前窗体是脏的;将提示用户保存当前数据,否则,将创建一个新的鸟类数据集合,并将窗体中所有先前的条目清除。

    ''' <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

打开文件菜单选项的点击事件处理程序紧随其后;此函数在打开新的鸟类数据文件到应用程序之前也检查是否为脏窗体。如果窗体不是脏的,应用程序将调用 Open 函数,该函数将允许用户导航并打开一个文件进行查看或编辑。

    ''' <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

接下来,打开方法使用打开文件对话框控件允许用户导航并选择一个鸟类数据文件。一旦选定,文件将被反序列化到本地鸟类集合并可供显示。

    ''' <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

保存菜单选项点击事件处理程序就在其后面。此函数使用保存文件对话框允许用户设置文件名或文件路径。一旦设置了文件路径,应用程序就会将鸟类集合中包含的数据序列化,并将其保存到磁盘。

    ''' <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

下一段代码与保存非常相似;它允许用户使用替换名称将当前鸟类数据文件保存到本地硬件。

    ''' <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

工具栏的保存按钮紧随其后;它仅调用保存菜单项点击事件来保存鸟类数据文件。

    ''' <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

保存当前鸟类函数用于将当前鸟类数据对象的值设置为与窗体控件的内容匹配。

    ''' <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

下一个区域称为 Bird Data Management;本节包含用于管理鸟类数据和鸟类数据集合的方法。此区域中的第一个函数用于将新鸟添加到集合中。该函数保存当前鸟类,创建一个新的空鸟类对象,将新的鸟类数据对象添加到鸟类集合中,然后将窗体标记为脏。

#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

下一个函数用于从集合中删除鸟类。删除鸟类后;当前位置将更新,并且窗体将使用替换的鸟类信息重新加载。

    ''' <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

下一个函数用于支持查找特定鸟类。当点击事件处理程序执行时,将创建一个查找窗体(Form3)的新实例,并设置查找窗体 BirdNameUpdated 事件的事件处理程序。

    ''' <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

下一个函数用于按名称查找特定鸟类。当查找窗体引发事件,指示用户想要查找集合中具有特定名称的鸟类时,此函数将遍历集合直到找到匹配项,然后它将该鸟类设置为当前鸟类并更新窗体以显示该鸟类的信息。

    ''' <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

下一个函数用于显示一个包含当前鸟类数据列表中所有鸟类的窗体。Form2 包含一个数据网格视图控件,它接受一个鸟类数据列表作为构造函数的参数。当创建窗体并传递当前鸟类数据的副本时,该数据将绑定到数据网格视图控件并显示给用户。

    ''' <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

下一个函数在当前鸟类更改时调用。它从当前鸟类对象重新加载所有窗体控件。

    ''' <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

此类中包含的下一个区域包含两个函数,用于控制鸟类数据列表的前向和后向导航。在这两种情况下,当前鸟类都通过调用 SaveCurrentBird 函数来保存。在本地保存当前鸟类后,将检查当前位置是否位于底部或顶部限制,如果可能,将递增或递减位置。更新当前位置后,将当前鸟类数据设置为更新位置处的鸟类数据,然后重新加载窗体。

#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

此类代码的最后一个区域用于响应更改将窗体标记为脏。请注意,而不是使用值更改事件来设置脏窗体,而是使用了其他事件,例如文本框控件的按键事件,来提供更改的指示。原因是,如果打开一个鸟类数据文件并浏览列表,值会发生更改,并且窗体会被标记为脏,即使实际上没有发生更改。

#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

以上是对应用程序主窗体中代码的讨论。

代码:列出所有鸟类窗体 (Form2.vb)

用于显示当前鸟类数据列表中所有鸟类的窗体非常简单。该窗体包含一个数据网格视图控件,用于显示鸟类数据列表。构造函数已修改为接受鸟类数据列表作为参数;构造函数将数据网格视图控件绑定到鸟类数据列表,并隐藏第一列(包含用于唯一标识记录的 Guid )。

此类代码将全部提供。

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

以上是 Form2 类的说明。

代码:查找鸟类窗体 (Form3.vb)

此窗体用于向用户提供当前鸟类数据列表中所有鸟类名称的列表。用户可以从列表中查看和选择鸟类名称,然后单击窗体的“查找”按钮;这将引发一个事件,主窗体将使用该事件将匹配的鸟类加载到窗体中。

该类以常规的默认库导入、命名空间声明和类声明开始。

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

在类声明之后,声明了一个委托和事件;这些用于在用户从窗体的列表中选择鸟类并单击窗体的“查找”按钮时通知主窗体。BirdNameUpdateEventArgs 被声明为一个单独的类;该类将用于包含选定的鸟类名称,并在引发 event 时将该信息提供给主窗体。

    ' 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

构造函数已修改为接受鸟类数据列表作为参数;每当创建窗体实例时,构造函数都会遍历鸟类数据列表,并将每个鸟类名称添加到用于显示鸟类名称的 listbox 控件中。

    ''' <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

查找按钮点击事件处理程序创建 event 参数的一个实例,并将 listbox 控件的选定项添加到事件参数中。设置后,将引发 event ,引发 event 将强制主窗体将选定鸟类的相关信息加载到窗体控件中。

    ''' <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

BirdNameUpdateEventArgs 类用于包含鸟类名称,并促进在触发鸟类名称更新事件时将鸟类名称传递给主窗体。此类可以扩展以包含更多属性。

''' <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

以上是对查找窗体类(Form3.vb)的讨论。

摘要

本文介绍了一种在不实际使用数据库支持应用程序的情况下,在 WinForms 应用程序中持久化和管理数据的方法。这种方法可能在许多用户不与其他用户共享信息的应用程序中有用。即使示例展示了管理鸟类信息集合的方法,它也可以用于许多其他目的,例如维护飞蝇模式库,或者您喜欢的昆虫收藏、工具或设备库存等。

历史

  • 2008年6月3日:初始版本
© . All rights reserved.