MergedDataGridView 控件
一个 DataGridView 控件,允许在合并的行中显示一些额外信息。 使用 Visual Basic.NET 2008 和 Framework 3.5。
引言
众所周知,DataGridView
控件不允许我们合并单元格,如果我们稍微思考一下,我们可以问自己,“为什么?”。 好吧,DataGridView
绑定到一个数据源(即使您没有定义它),并且每个单元格代表记录中的一个字段,那么合并的单元格将属于哪个字段? 也许,正是因为这个原因,微软没有包含这个特性。 但是,有时我们可能想要显示一些额外的信息,唯一的解决方案是弹出一个表单/消息框,或者“窃取”当前表单中的一些空间并用文本框、组合框等填充它。
此自定义的目的是在 DataGridView
中显示一些额外信息。 它基本上使用一个 RichTextBox
,插入到网格中并根据父行的大小调整大小。 父行必须具有唯一的 ID,该 ID 将是文本框的名称。 然后,这将用于调整大小并将 RichTextBox
放置在正确的位置。
我还包括了一些图标动画和网格自定义,以改善最终外观。
使用代码
首先,您必须在应用程序中包含类 MergedDataGridView
。 构建项目后,MergedDataGridView
控件将在工具箱中可用。 然后,只需将其拖到您的表单即可。
接下来,您需要为 MergedDataGridView
定义自定义属性
With Me.MergedDataGridView1
' Define the datasource
.DataSource = ds.Tables(0).DefaultView
' Custom definitions for the RichTextBox
.StartColumnIndex = 1
.EndColumnIndex = 7
.RowHeight = 60
' Custom definitions for the DataGridView
.AllowUserToAddRows = False
.AllowUserToDeleteRows = False
.RowsDefaultCellStyle.BackColor = Color.White
.AlternatingRowsDefaultCellStyle.BackColor = Color.AliceBlue
.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells)
End With
之后,您可以包含两个 DataGridViewImageColumn
,它们将用于显示 RichTextBox
和显示包含信息的 MessageBox
。
' Create an image column in the datagrid that will open the merged row
Dim ImageColumn1 As New DataGridViewImageColumn
ImageColumn1.DefaultCellStyle.Alignment = DataGridViewContentAlignment.TopCenter
ImageColumn1.Image = My.Resources.DownArrow
ImageColumn1.Width = 25
' Create an image column in the datagrid that will open an extra window
Dim ImageColumn2 As New DataGridViewImageColumn
ImageColumn2.DefaultCellStyle.Alignment = DataGridViewContentAlignment.TopCenter
ImageColumn2.Image = My.Resources.Info
ImageColumn2.Width = 25
' Add the two columns to the datagridview
Me.MergedDataGridView1.Columns.AddRange(New _
DataGridViewImageColumn() {ImageColumn1, ImageColumn2})
最后,在 CellMouseClick
事件中,检查用户是否单击了正确的列;如果是,则添加新行
' Add a new row in the correct postion (e.RowIndex + 1)
Dim rowPos As Integer = e.RowIndex + 1
Dim dv As DataView = Me.MergedDataGridView1.DataSource
Dim row As DataRow = dv.Table.NewRow()
dv.Table.Rows.InsertAt(row, rowPos)
' Get the text from the hidden columns that will be used to fill the RichTextBox
Dim mergedRowText As New System.Text.StringBuilder
mergedRowText.AppendLine(Me.MergedDataGridView1("Description", e.RowIndex).Value.ToString)
mergedRowText.AppendLine(Me.MergedDataGridView1("Link", e.RowIndex).Value.ToString)
' Call the AddMergedRow sub
Me.MergedDataGridView1.AddMergedRow(rowPos, mergedRowText.ToString)
或删除它
' Remove the row from the datasource
Dim rowPos As Integer = e.RowIndex + 1
Dim dv As DataView = Me.MergedDataGridView1.DataSource
dv.Table.Rows.RemoveAt(rowPos)
' Call the RemoveMergedRow sub
Me.MergedDataGridView1.RemoveMergedRow(Me.MergedDataGridView1(0, _
e.RowIndex).Value)
正如您在随附的示例中看到的那样,表单中使用的其他代码用于验证、错误处理和通用动画。
查看控件
该控件只有两个方法:AddMergedRow
和 RemoveMergedRow
,以及三个属性。 这些属性只是指示 RichTextBox
将从哪一列开始、结束以及它将具有的高度。
AddMergedRow
查找前一行的编号(ID),这将是父行,并在新行中创建一个新的 RichTextBox
,并将该 ID 作为名称。
''' <summary>
''' Adds a new row with a merged cell using a richtextbox
''' </summary>
''' <param name="rowIndex">Index where the row will be added</param>
''' <param name="cellText">Text that will be displayed on the RichTextBox</param>
''' <remarks></remarks>
Public Sub AddMergedRow(ByVal rowIndex As Integer, ByVal cellText As String)
Try
Me.SuspendLayout()
' Defines the location/size of the textbox
Dim x As Integer = _
Me.GetColumnDisplayRectangle(Me.StartColumnIndex, False).Left + 1
Dim y As Integer = Me.GetRowDisplayRectangle(rowIndex, False).Top
Dim w As Integer = _
Me.GetColumnDisplayRectangle(Me.EndColumnIndex, False).Right - x - 2
Dim h As Integer = Me.GetRowDisplayRectangle(rowIndex, False).Size.Height - 1
' Gets the ID from the previous row, that will be used for the name
' of the textbox. This ID will be used to find the control for the row
Dim parentRowID As Integer = Me(0, rowIndex - 1).Value
' Creates a new textbox and place it in the right position
Dim rtb As New RichTextBox
With rtb
.Name = parentRowID
.Text = cellText
.Multiline = True
.BorderStyle = BorderStyle.None
.ScrollBars = ScrollBars.Vertical
.ReadOnly = True
.Font = New Font(Me.DefaultCellStyle.Font, Me.DefaultCellStyle.Font.Style)
.SetBounds(x, y, w, h)
End With
Me.Controls.Add(rtb)
' Define the same color for the RichTextBox as the row color
rtb.BackColor = Me(0, rowIndex).InheritedStyle.BackColor
' Define the row height
Me.Rows(rowIndex).Height = Me.RowHeight
' Define a new image for the imagecell (up arrow)
Dim arrow As DataGridViewImageCell = Me(Me.ColumnCount - 2, rowIndex - 1)
arrow.Value = My.Resources.UpArrow
Catch ex As Exception
Throw New ArgumentException(ex.Message)
Finally
Me.ResumeLayout()
End Try
End Sub
第二个方法 RemoveMergedRow
查找父行并将其从网格中删除。
''' <summary>
''' Removes the cell (RichTextBox) from the DataGridView
''' </summary>
''' <param name="rowID">ID of the row</param>
''' <remarks></remarks>
Public Sub RemoveMergedRow(ByVal rowID As Integer)
Try
' Find the control in the DataGridView and remove it
Dim ctrl() As Control = Me.Controls.Find(rowID.ToString, False)
If ctrl.Length = 1 Then
Me.Controls.Remove(ctrl(0))
End If
' Define a new image for the imagecell (down arrow)
Dim arrow As DataGridViewImageCell = Me(Me.ColumnCount - 2, Me.CurrentRow.Index)
arrow.Value = My.Resources.DownArrow
Catch ex As Exception
Throw New ArgumentException(ex.Message)
Finally
Me.ResumeLayout()
End Try
End Sub
Paint
事件排列 RichTextBox
es 的位置并调整大小。
由于在排序后很难计算位置并保持父行下方的空行,因此我已在 ColumnAdded
事件中关闭了排序。
关注点
此控件不仅在 DataGridView
控件上显示一些额外信息,而且还演示了如何自定义网格和处理行定位,这可能对其他项目有用。
我真的希望这能帮助改进您的项目,或者帮助您获得一些新想法。