如何于DataGridView中使用计算字段


图表1

 


图表2

 

读者呆呆询问了好几次如何于DataGridView控件中使用计算字段的问题。在此我们就通过一个完整的范例一次清楚呈现。事实上,如果绑定至一个数据来源的DataGridView控件还必须内含计算字段的话,必须让DataGridView控件采用虚拟模式(也就是必须将 VirtualMode 属性设定成 True),而且您必须自行在CellValueNeeded事件处理例程中完成运算字段值的撷取作业。

 

图表1所示者是我们所撰写的程序范例,您可以在其中的DataGridView控件中新增、修改与删除数据,重点在于,其中的「年龄」资料行是根据「出生日期」计算而来。而且每当您更改「出生日期」数据行中的日期值,则在移出该储存格(Cell)后,年龄就会立即计算出来即使是新增的数据记录也会如此。以下我们说明本程序范例的设计技巧。

 

首先,您必须如图表2所示,在窗体上加入所需的各个控件,然后撰写下列程序代码。我们是将窗体的程序代码全数列出,其中已加上完整的批注,另外,本程序使用到frmStatus.vb,因此务必记得将此文件汇入您的项目中:

 

Option Strict On
Imports System.Data.SqlClient
Imports System.IO
Public Class CH13_DemoForm001

  Private myDataSet As DataSet

  Private Sub CH13_DemoForm001_Load(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles MyBase.Load
    ' 呼叫 LoadDataToDataSet() 函式来连接至数据来源并传回所需的 DataSet 对象。
    myDataSet = LoadDataToDataSet()

    If myDataSet IsNot Nothing Then

      ' BindingSource 组件系结至数据集对象中的「章立民研究室」数据表。
      Me.BindingSource1.DataMember = "章立民研究室"
      Me.BindingSource1.DataSource = myDataSet

      ' BindingNavigator 控件的数据来源也设定成 BindingSource 组件,如此一来,
      ' 就可以使用 BindingNavigator 控件去导览 DataGridView 控件中的数据列。
      Me.BindingNavigator1.BindingSource = Me.BindingSource1

      ' 自订 DataGridView 控件。
      CustomizeMyDataGridView()
    End If
  End Sub

  Private Sub CustomizeMyDataGridView()

    ' 由于我们要自订各个数据行类型,因此必须
    ' AutoGenerateColumns 属性设定成 False
    DataGridView1.AutoGenerateColumns = False

    ' 设定奇数资料列的背景色。
    DataGridView1.AlternatingRowsDefaultCellStyle.BackColor = _
      SystemColors.InactiveCaptionText

    ' 设定用户一次只能选取一个储存格、数据列或数据行。
    DataGridView1.MultiSelect = False

    ' 设定采用储存格选取模式。
    DataGridView1.SelectionMode = DataGridViewSelectionMode.CellSelect

    ' 设定数据列的高度。
    Me.DataGridView1.RowTemplate.Height = 30

    ' 由于我们的 DataGridView 控件将会内含未系结数据行,因此必须
    ' VirtualMode 属性设定成True,也就是必须启用虚拟模式。
    DataGridView1.VirtualMode = True

    ' DataGridView 控件的数据来源设定成 BindingSource 组件。
    Me.DataGridView1.DataSource = Me.BindingSource1

    ' 接下来的程序代码要自订各个数据行类型.....

    '
    ' 资料行:员工编号,文字方块
    '
    ' 建立一个 DataGridViewTextBoxColumn 对象并设定其相关属性。
    '
    Dim colEmployeeId As New DataGridViewTextBoxColumn()
    ' 设定来源字段。
    colEmployeeId.DataPropertyName = "员工编号"
    ' 设定数据行标题。
    colEmployeeId.HeaderText = "编号"
    colEmployeeId.Name = "员工编号"
    ' 将此数据行设定成只读的。
    colEmployeeId.ReadOnly = True
    ' 设定数据行的宽度。
    colEmployeeId.Width = 60
    ' DataGridViewTextBoxColumn 对象新增至 DataGridView 控件的数据行集合中。
    DataGridView1.Columns.Add(colEmployeeId)

    '
    ' 资料行:姓名,文字方块
    '
    ' 建立一个 DataGridViewTextBoxColumn 对象并设定其相关属性。
    '
    Dim colName As New DataGridViewTextBoxColumn()
    ' 调整资料行的宽度使其足以显示出最宽的可见储存格(包括标题在内)。
    colName.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells
    ' 设定来源字段。
    colName.DataPropertyName = "姓名"
    ' 设定数据行标题。
    colName.HeaderText = "员工姓名"
    colName.Name = "姓名"
    colName.ReadOnly = False
    ' DataGridViewTextBoxColumn 对象新增至 DataGridView 控件的数据行集合中。
    DataGridView1.Columns.Add(colName)

    '
    ' 资料行:性别,下拉式清单方块
    '
    ' 建立一个 DataGridViewComboBoxColumn 对象并设定其相关属性。
    '
    Dim colGender As New DataGridViewComboBoxColumn()
    ' 调整资料行的宽度使其足以显示出标题。
    colGender.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader
    ' 设定来源字段。
    colGender.DataPropertyName = "性别"
    ' 设定下拉式清单中的选项。
    colGender.Items.AddRange(New String() {"", ""})
    ' 排序下拉式清单方块的内容。
    colGender.Sorted = True
    ' 停用数据行的排序功能。
    colGender.SortMode = DataGridViewColumnSortMode.NotSortable
    colGender.HeaderText = "性别"
    colGender.Name = "性别"
    colGender.ReadOnly = False
    ' DataGridViewComboBoxColumn 对象新增至 DataGridView 控件的数据行集合中。
    DataGridView1.Columns.Add(colGender)

    '
    ' 资料行:出生日期,自订格式化的文字方块
    '
    ' 建立一个 DataGridViewTextBoxColumn 对象并设定其相关属性。
    '
    Dim colBirthday As New DataGridViewTextBoxColumn()
    ' 调整资料行的宽度使其足以显示出最宽的可见储存格(包括标题在内)。
    colBirthday.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells
    ' 设定来源字段。
    colBirthday.DataPropertyName = "出生日期"
    ' 设定日期显示格式。
    colBirthday.DefaultCellStyle.Format = "MM-dd-yyyy"
    colBirthday.HeaderText = "出生月日年"
    colBirthday.Name = "出生日期"

    ' DataGridViewTextBoxColumn 对象新增至 DataGridView 控件的数据行集合中。
    DataGridView1.Columns.Add(colBirthday)

    '
    ' 资料行:年龄,未系结的资料行
    '
    ' 建立一个 DataGridViewTextBoxColumn 对象并设定其相关属性。
    '
    Dim colAge As New DataGridViewTextBoxColumn()
    ' 调整资料行的宽度使其足以显示出标题。
    colAge.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader
    colAge.HeaderText = "年龄"
    colAge.Name = "年龄"

    ' 将此资料行设定成只读,毕竟年龄是根据出生日期所计算出来。
    ' 如果没有将此数据行设定成只读,则必须通过 CellValuePush 事件处理例程
    ' 将所输入的数据写入数据来源。
    colAge.ReadOnly = True

    ' 设定当引发 DataGridView 控件的 CellValueNeeded 事件时所要执行的
    ' 事件处理例程。请特别注意,未系结资料行是通过CellValueNeeded 事件
    ' 来撷取资料。
    AddHandler DataGridView1.CellValueNeeded, AddressOf colAge_CellValueNeeded

    ' DataGridViewTextBoxColumn 对象新增至 DataGridView 控件的数据行集合中。
    DataGridView1.Columns.Add(colAge)

    '
    ' 资料行:婚姻状况,下拉式清单方块
    '
    ' 建立一个 DataGridViewComboBoxColumn 对象并设定其相关属性。
    '
    Dim colMaritalStatus As New DataGridViewComboBoxColumn()
    ' 调整资料行的宽度使其足以显示出标题。
    colMaritalStatus.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader
    ' 设定来源字段。
    colMaritalStatus.DataPropertyName = "婚姻状况"
    ' 设定下拉式清单中的选项。
    colMaritalStatus.Items.AddRange(New String() {"已婚", "未婚"})
    ' 排序下拉式清单方块的内容。
    colMaritalStatus.Sorted = True
    ' 停用数据行的排序功能。
    colMaritalStatus.SortMode = DataGridViewColumnSortMode.NotSortable
    colMaritalStatus.HeaderText = "婚姻状况"
    colMaritalStatus.Name = "婚姻状况"
    colMaritalStatus.ReadOnly = False
    ' DataGridViewTextBoxColumn 对象新增至 DataGridView 控件的数据行集合中。
    DataGridView1.Columns.Add(colMaritalStatus)

    '
    ' 资料行:部门,下拉式清单方块
    '
    ' 建立一个 DataGridViewComboBoxColumn 对象并设定其相关属性。
    '
    ' 请注意,此数据行之下拉式清单方块的选项内容是来自数据集 myDataSet
    '  当中的「公司部门」资料表。
    '
    Dim colDepartment As New DataGridViewComboBoxColumn()
    colDepartment.DataPropertyName = "部门"
    ' 将下拉式清单方块系结至数据集 myDataSet 当中的「公司部门」资料表。
    colDepartment.DataSource = myDataSet.Tables("公司部门")
    colDepartment.ValueMember = "部门"
    colDepartment.DisplayMember = "部门"
    colDepartment.HeaderText = "任职部门"
    colDepartment.Name = "部门"
    colDepartment.ReadOnly = False
    colDepartment.Width = 120
    ' DataGridViewComboBoxColumn 对象新增至 DataGridView 控件的数据行集合中。
    DataGridView1.Columns.Add(colDepartment)
End Sub

' 此事件处理例程负责替未系结数据行撷取数据。
Private Sub colAge_CellValueNeeded(ByVal sender As Object, _
  ByVal e As DataGridViewCellValueEventArgs)

  If e.ColumnIndex = CType(sender, DataGridView).Columns("年龄").Index Then
      Dim age As Integer
      Dim birthDate As DateTime = _
        CDate(CType(sender, DataGridView).Rows( _
        e.RowIndex).Cells("出生日期").Value)
      age = DateTime.Today.Year - birthDate.Year

      If (DateTime.Today.DayOfYear < birthDate.DayOfYear) Then
          age -= 1
      End If
      e.Value = age
  End If
End Sub

Private Sub DataGridView1_CellEndEdit(ByVal sender As Object, _
  ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) _
  Handles DataGridView1.CellEndEdit
  If e.ColumnIndex = CType(sender, DataGridView).Columns("出生日期").Index Then
      Dim age As Integer
      Dim birthDate As DateTime = CDate(CType( _
        sender, DataGridView).Rows(e.RowIndex).Cells("出生日期").Value)
      age = DateTime.Today.Year - birthDate.Year

      If (DateTime.Today.DayOfYear < birthDate.DayOfYear) Then
          age -= 1
      End If
      CType(sender, DataGridView).Rows( _
        e.RowIndex).Cells("年龄").Value = age.ToString

  End If
End Sub

' 本程序会连接至数据来源并建立所需的 DataSet 对象。
Private Function LoadDataToDataSet() As DataSet
  ' 利用 SqlConnectionStringBuilder 对象来构建连接字符串。
  Dim sqlStringBuilder As New SqlConnectionStringBuilder()
  sqlStringBuilder.DataSource = "(local)\SQLEXPRESS"
  sqlStringBuilder.InitialCatalog = "北风贸易"
  sqlStringBuilder.IntegratedSecurity = True

  ' 建立一个数据集。
  Dim ds As New DataSet()

  ' 显示一个状态讯息对话框来表示我们目前要尝试连结至 SQL Server Express
  Dim frmStatusMessage As New frmStatus

  frmStatusMessage.Show("连接至SQL Server Express ....")

  Try
      Using northwindConnection As _
        New SqlConnection(sqlStringBuilder.ConnectionString)

        Dim cmdLiming As New SqlCommand( _
          "SELECT DISTINCT 部门FROM dbo.章立民研究室;" & _
          "SELECT 员工编号,姓名,性别,婚姻状况,部门,出生日期,玉照 " & _
          "FROM dbo.章立民研究室", northwindConnection)

        northwindConnection.Open()

        Using drLiming As SqlDataReader = cmdLiming.ExecuteReader()

            ds.Load( _
             drLiming, _
             LoadOption.OverwriteChanges, _
             New String() {"公司部门", "章立民研究室"})

        End Using
      End Using

      ' 设定「出生日期」字段的默认值。

      ds.Tables("章立民研究室").Columns("出生日期").DefaultValue = DateTime.Now

  Catch exc As Exception

      frmStatusMessage.Close()

      MessageBox.Show( _
        "要能够顺利执行本范例程序,您的计算机必须已安装SQL Server " & _
        "Express,并且必须已附加了本书所附的「北风贸易」数据库。" & _
        "关于如何安装SQL Server Express,请参阅附录或相关文件说明。")

      ' 无法连接至SQL Server
      Return Nothing
  End Try

  frmStatusMessage.Close()
  Return ds
End Function

End Class

 

posted on 2006-12-15 09:57  章立民研究室  阅读(15594)  评论(12编辑  收藏  举报

导航