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

MergedDataGridView 控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.81/5 (27投票s)

2009 年 4 月 23 日

CPOL

2分钟阅读

viewsIcon

112009

downloadIcon

8395

一个 DataGridView 控件,允许在合并的行中显示一些额外信息。 使用 Visual Basic.NET 2008 和 Framework 3.5。

MergedDataGridView.png

引言

众所周知,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)

正如您在随附的示例中看到的那样,表单中使用的其他代码用于验证、错误处理和通用动画。

查看控件

Class.png

该控件只有两个方法:AddMergedRowRemoveMergedRow,以及三个属性。 这些属性只是指示 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 事件排列 RichTextBoxes 的位置并调整大小。

由于在排序后很难计算位置并保持父行下方的空行,因此我已在 ColumnAdded 事件中关闭了排序。

关注点

此控件不仅在 DataGridView 控件上显示一些额外信息,而且还演示了如何自定义网格和处理行定位,这可能对其他项目有用。

我真的希望这能帮助改进您的项目,或者帮助您获得一些新想法。

© . All rights reserved.