на главную все статьи


 

ASP.NET - объединение ячеек в GridView

В ASP.NET есть очень замечательный компонент GridView, его мощь трудно переоценить. Любым средством, конечно нужно уметь пользоваться, но иногда без трюков не обойтись. В этой статье рассказывается, как в GridView добавить в шапку таблицы вторую строку и объединить в ней ячейки. Т.е. мы хотим сделать что-то подобное:

Колонка 1 Объединение Колонка 4
Колонка 2 Колонка 3
       

Используя прием, описаный в этой статье, можно достичь ЛЮБОГО желаемого объединения ячеек в таблице. Например такого:

Колонка 1 Колонка 2 Колонка 3 Колонка 4
Объединение      
     
     

Первое, что нам необходимо сделать - это получить доступ к внутреннему объекту нашего GridView с типом Table, строками и ячейками которого мы будем достигать требуемого эффекта:
Dim gv As GridView
Dim t As Table

t=CType(gv.Controls(0), Table)
Теперь, используя стандартные коллекции Rows и Cells полученного Table, а также свойства ячеек ColumnSpan и RowSpan осуществляем любые необходимые объединения. Строка шапки имеет индекс 0 (также можно воспользоваться свойством HeaderRow самого GridView), строки с данными из таблицы имеют индексы 1, 2 и т.д.
Далее покажем работу с GridView на примере работы с шапкой:
Dim row = New GridViewRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal)
Dim r = gv.HeaderRow  'или CType(gv.Controls(0), Table).Rows(0)
Копируем строку шапки:
Dim cell As TableHeaderCell

For Each rcell As TableCell In r.Cells
   cell = New TableHeaderCell
   cell.Text = rcell.Text 'можем скопировать заголовки из шапки
   cell.Style("text-align") = "center" 'можем задать какой-то стиль
   row.Cells.Add(cell)
Next
Далее для нужных ячеек i устанавливаем объединение по горизонтали:
row.Cells(i).ColumnSpan="3" 'например, для 3-х объединяемых ячеек
Для ячеек, которые не будут объединены по горизонтали, устанавливаем объединение по вертикали на 2 строки:
row.Cells(i).RowSpan="2"
Не забудьте, что в "родной" строке шапки нужно удалить ячейки с индексами колонок, которые мы не объединяем по горизонтали (по индексу которых делали RowSpan="2"). А также необходимо удалить ячейки из нашей вновь добавляемой строки, потому что в местах объединения в ней ячеек (колонок шапки) меньше, чем в "родной" строке шапки:
row.Cells.RemoveAt(i)
r.Cells.RemoveAt(i)
И, наконец, добавляем нашу дополнительную строку на верх в шапку таблицы:
CType(gv.Controls(0), Table).Rows.AddAt(0, row)
Как видим, принцип довольно простой, расстраивает только одно, что необходимо не запутаться и удалить из обоих строк шапки требуемые ячейки, кроме того, не удобно каждый раз в программу вставлять такие большие куски кода для обработки шапки каждого GridView. Хорошо было бы написать универсальную процедуру, в качестве параметров которой передавать как-нибудь (понятненько и несложненько), что мы хотим объединить, а заодно и тексты для объединяемых ячеек. Например, вот так:
Dim a(,) As String = {{"Объединение 1", "4", "2"}, {"Объединение 2", "6", "4"}} 'и т.д., понятно, что перечень объединений может быть не ограничен
ApplyGridViewHeader(gv, a) 
Где a(,) - ясное дело, динамический 2-х мерный массив строк, "Объединение 1" - это название объединения, следующее значение - индекс, начиная с которого будем объединять ячейки, а следующее значение - количество объединяемых ячеек.

Но об этом чуть позже. У нас осталась еще одна важная вещь - в какой момент производить обработку GridView? В Page_Load, Page_PreRender ? В произвольном месте кода страницы производить эту манипуляцию не удается, после первого postback вся наша конструкция "съезжает", сказывается работа GridView, связанная с ViewState этого контрола. И даже обработка во всемогущих событиях страницы PreRender и PreRenderComplete нас не спасает.
Поможет нам не такое популярное событие SaveStateComplete. Для желающих расширить свой кругозор в жизненном цикле страницы ASP.NET привожу ссылку, там есть очень наглядненькая (моя ненаглядненькая :) картиночка от Microsoft жизненный цикл и события страниц ASP.NET.

Важно! производить вышеописанные манипуляции с GridView нужно в событии страницы SaveStateComplete

Ну, и напоследок, для тех, кто хочет съэкономить свое время, и избежать алгоритмических баталий с ячейками GridView, текст написанной мной процедуры ApplyGridViewHeader(gv, a) по объединению ячеек в шапке таблицы (чуть выше я приводил пример вызова этой процедуры):
Namespace MyNamespace
    ' статический класс для работы с элементами управления

    Public Class WebControlsProcsClass
        Public Shared Sub ApplyGridViewHeader(ByRef gv As GridView, ByRef a(,) As String)
           'процедура написана таким образом, что в нее всегда должны передаваться индексы с учетом только фактически отображаемых колонок
           'т.е. при вычислении индекса объединяемой колонки (передаваемой в качестве параметра в процедуру) считается,
           'что колонок со свойством Visible = false в таблице как бы нет.
           'индексы (передаваемые в качестве параметров в процедуру) указываются по исходному порядку необъединенных колонок

            If gv.Rows.Count > 0 Then
                Dim row = New GridViewRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal)
                Dim r = gv.HeaderRow
                Dim cell As TableHeaderCell

                Dim i, j As Integer

                'следующие два цикла удаляют ячейки "родной" строки шапки таблицы, соответствующие колонкам с Visible = false
                'если таковые, конечно, имеются
                For i = 0 To gv.Columns.Count - 1
                    If Not (gv.Columns(i).Visible) Then
                        r.Cells(i).ColumnSpan = 100
                    End If
                Next

                i = 0
                While i < r.Cells.Count
                    If r.Cells(i).ColumnSpan = 100 Then
                        r.Cells.RemoveAt(i)
                    Else : i = i + 1
                    End If
                End While

                'копируем "родную" строку шапки
                For Each rcell As TableCell In r.Cells
                    cell = New TableHeaderCell
                    cell.Text = rcell.Text
                    cell.Style("text-align") = "center"

                    row.Cells.Add(cell)
                Next

                'для нужных ячеек в верхней строке, прописываем тексты объединяющих ячеек и их ColumnSpan
                For i = 0 To a.GetUpperBound(0)
                    row.Cells(a(i, 1)).Text = a(i, 0)
                    row.Cells(a(i, 1)).ColumnSpan = a(i, 2)
                Next

                'идем по верхней строке у оставшихся ячеек (не задействованных) в предыдущем цикле ставим им RowSpan = 2
                'одновременно ячееки с таким же индексом в нижней строке помечаем на удаление
                For i = 0 To row.Cells.Count - 1
                    If row.Cells(i).ColumnSpan < 2 Then
                        row.Cells(i).RowSpan = 2
                        r.Cells(i).ColumnSpan = 100
                    Else
                        'пропускаем ячейки на которые распространяется ColumnSpan
                        i = i + row.Cells(i).ColumnSpan - 1
                    End If
                Next

                'удаляем помеченные ячейки в нижней строке
                i = 0
                While i < r.Cells.Count
                    If r.Cells(i).ColumnSpan = 100 Then
                        r.Cells.RemoveAt(i)
                    Else : i = i + 1
                    End If
                End While

                'идем по верхней строке удаляем соответствующее ColumnSpan количество ячеек после ячеек имеющих ColumnSpan > 1 
                i = 0
                While i < row.Cells.Count
                    If row.Cells(i).ColumnSpan > 1 Then
                        For j = 1 To row.Cells(i).ColumnSpan - 1
                            row.Cells.RemoveAt(i + 1)
                        Next
                    End If
                    i = i + 1
                End While

                CType(gv.Controls(0), Table).Rows.AddAt(0, row)
            End If
        End Sub
    End Class
End Namespace


 


автор:
Иван Токарев
оригинал статьи Объединение ячеек в GridView
www.webinformation.ru





Все статьи на этом сайте написаны автором сайта, при цитировании или копировании материалов ссылка на источник обязательна.