Ответ 1
Эта статья должна указывать на вас в правильном направлении. Вы можете программно создать строку и добавить ее в коллекцию в позиции 0.
У меня есть ASP.NET GridView, у которого есть столбцы, которые выглядят так:
| Foo | Bar | Total1 | Total2 | Total3 |
Можно ли создать заголовок в двух строках, который выглядит следующим образом?
| | Totals |
| Foo | Bar | 1 | 2 | 3 |
Данные в каждой строке будут оставаться неизменными, так как это просто подходит для заголовка и уменьшает горизонтальное пространство, которое занимает сетка.
Весь GridView сортируется в случае, если это имеет значение. Я не предполагаю, что добавленный столбец "Totals" будет иметь любую функцию сортировки.
Edit:
Основываясь на одной из приведенных ниже статей, я создал класс, который наследуется от GridView и добавляет вторую строку заголовка.
namespace CustomControls
{
public class TwoHeadedGridView : GridView
{
protected Table InnerTable
{
get
{
if (this.HasControls())
{
return (Table)this.Controls[0];
}
return null;
}
}
protected override void OnDataBound(EventArgs e)
{
base.OnDataBound(e);
this.CreateSecondHeader();
}
private void CreateSecondHeader()
{
GridViewRow row = new GridViewRow(0, -1, DataControlRowType.Header, DataControlRowState.Normal);
TableCell left = new TableHeaderCell();
left.ColumnSpan = 3;
row.Cells.Add(left);
TableCell totals = new TableHeaderCell();
totals.ColumnSpan = this.Columns.Count - 3;
totals.Text = "Totals";
row.Cells.Add(totals);
this.InnerTable.Rows.AddAt(0, row);
}
}
}
Если вы новичок в ASP.NET, как я, я должен также указать, что вам нужно:
1) Зарегистрируйте свой класс, добавив такую строку в свою веб-форму:
<%@ Register TagPrefix="foo" NameSpace="CustomControls" Assembly="__code"%>
2) Измените asp: GridView в вашей предыдущей разметке на foo: TwoHeadedGridView. Не забывайте закрывающий тег.
Другое редактирование:
Вы также можете сделать это, не создавая собственный класс.
Просто добавьте обработчик событий для события DataBound вашей сетки следующим образом:
protected void gvOrganisms_DataBound(object sender, EventArgs e)
{
GridView grid = sender as GridView;
if (grid != null)
{
GridViewRow row = new GridViewRow(0, -1,
DataControlRowType.Header, DataControlRowState.Normal);
TableCell left = new TableHeaderCell();
left.ColumnSpan = 3;
row.Cells.Add(left);
TableCell totals = new TableHeaderCell();
totals.ColumnSpan = grid.Columns.Count - 3;
totals.Text = "Totals";
row.Cells.Add(totals);
Table t = grid.Controls[0] as Table;
if (t != null)
{
t.Rows.AddAt(0, row);
}
}
}
Преимущество настраиваемого элемента управления заключается в том, что вы можете увидеть дополнительную строку заголовка в представлении дизайна своей веб-формы. Однако метод обработчика событий немного проще.
Эта статья должна указывать на вас в правильном направлении. Вы можете программно создать строку и добавить ее в коллекцию в позиции 0.
Я принял подход к принятому ответу, но добавил заголовок к существующему GridView вместо пользовательского унаследованного GridView.
После привязки моего GridView я делаю следующее:
/*Create header row above generated header row*/
//create row
GridViewRow row = new GridViewRow(0, -1, DataControlRowType.Header, DataControlRowState.Normal);
//spanned cell that will span the columns I don't want to give the additional header
TableCell left = new TableHeaderCell();
left.ColumnSpan = 6;
row.Cells.Add(left);
//spanned cell that will span the columns i want to give the additional header
TableCell totals = new TableHeaderCell();
totals.ColumnSpan = myGridView.Columns.Count - 3;
totals.Text = "Additional Header";
row.Cells.Add(totals);
//Add the new row to the gridview as the master header row
//A table is the only Control (index[0]) in a GridView
((Table)myGridView.Controls[0]).Rows.AddAt(0, row);
/*fin*/
Вам нужно будет создать класс, который расширяет gridview, а затем переопределяет метод CreateRow.
попробуйте this в качестве отправной точки
Но когда вы сохраняете данные, и если на сервере возникает ошибка, произойдет несоосность строк
Примечание для тех, кто решил использовать метод RowDataBound в VB.NET
Если у вас появилось слишком много лишних строк заголовка, добавьте оператор If, который будет выполняться только в том случае, если строка заголовка gridview не имеет значения (что означает, что в данный момент она привязана)
If grid.HeaderRow Is Nothing Then
Добавьте t.EnableViewState = false;
после добавления строки:
Dim t As Table = TryCast(grid.Controls(0), Table)
If t IsNot Nothing Then
t.Rows.AddAt(0, row)
End If
t.EnableViewState = false;
Обратитесь к fooobar.com/questions/161771/...
i создал этот пример решения
Для запуска в вашей локальной системе потребуется создать 2 файла (один для элемента управления и один aspx), вы можете либо сделать это один проект, либо 2 проекта.
Файл aspx == > Программа тестирования
public class GridViewPlus : GridView
{
public event EventHandler<CustomHeaderEventArgs> CustomHeaderTableCellCreated;
private GridViewPlusCustomHeaderRows _rows;
public GridViewPlus() : base ()
{
_rows = new GridViewPlusCustomHeaderRows();
}
/// <summary>
/// Allow Custom Headers
/// </summary>
public bool ShowCustomHeader { get; set; }
[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
[MergableProperty(false)]
public GridViewPlusCustomHeaderRows CustomHeaderRows
{
get {return _rows; }
}
protected virtual void OnCustomHeaderTableCellCreated(CustomHeaderEventArgs e)
{
EventHandler<CustomHeaderEventArgs> handler = CustomHeaderTableCellCreated;
// Event will be null if there are no subscribers
if (handler != null)
{
// Use the () operator to raise the event.
handler(this, e);
}
}
protected override void OnRowCreated(GridViewRowEventArgs e)
{
if (ShowCustomHeader && e.Row.RowType == DataControlRowType.Header) return;
base.OnRowCreated(e);
}
protected override void PrepareControlHierarchy()
{
//Do not show the Gridview header if show custom header is ON
if (ShowCustomHeader) this.ShowHeader = false;
base.PrepareControlHierarchy();
//Safety Check
if (this.Controls.Count == 0)
return;
bool controlStyleCreated = this.ControlStyleCreated;
Table table = (Table)this.Controls[0];
int j = 0;
if (CustomHeaderRows ==null )return ;
foreach (TableRow tr in CustomHeaderRows)
{
OnCustomHeaderTableCellCreated(new CustomHeaderEventArgs(tr,j));
table.Rows.AddAt(j, tr);
tr.ApplyStyle(this.HeaderStyle);
j++;
}
}
}
public class GridViewPlusCustomHeaderRows : System.Collections.CollectionBase
{
public GridViewPlusCustomHeaderRows()
{
}
public void Add(TableRow aGridViewCustomRow)
{
List.Add(aGridViewCustomRow);
}
public void Remove(int index)
{
// Check to see if there is a widget at the supplied index.
if (index > Count - 1 || index < 0)
// If no widget exists, a messagebox is shown and the operation
// is cancelled.
{
throw (new Exception("Index not valid"));
}
else
{
List.RemoveAt(index);
}
}
public TableRow Item(int Index)
{
// The appropriate item is retrieved from the List object and
// explicitly cast to the Widget type, then returned to the
// caller.
return (TableRow)List[Index];
}
}
public class CustomHeaderEventArgs : EventArgs
{
public CustomHeaderEventArgs(TableRow tr ,int RowNumber )
{
tRow = tr;
_rownumber = RowNumber;
}
private TableRow tRow;
private int _rownumber = 0;
public int RowNumber { get { return _rownumber; } }
public TableRow HeaderRow
{
get { return tRow; }
set { tRow = value; }
}
}
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Example1();
GridViewExtension1.CustomHeaderTableCellCreated += new EventHandler<CustomHeaderEventArgs>(GridViewExtension1_CustomHeaderTableCellCreated);
}
void GridViewExtension1_CustomHeaderTableCellCreated(object sender, CustomHeaderEventArgs e)
{
TableRow tc = (TableRow)e.HeaderRow;
tc.BackColor = System.Drawing.Color.AliceBlue;
}
private void Example1()
{
System.Data.DataTable dtSample = new DataTable();
DataColumn dc1 = new DataColumn("Column1",typeof(string));
DataColumn dc2 = new DataColumn("Column2",typeof(string));
DataColumn dc3 = new DataColumn("Column3",typeof(string));
DataColumn dc4 = new DataColumn("Column4",typeof(string));
// DataColumn dc5 = new DataColumn("Column5",typeof(string));
dtSample.Columns.Add(dc1);
dtSample.Columns.Add(dc2);
dtSample.Columns.Add(dc3);
dtSample.Columns.Add(dc4);
// dtSample.Columns.Add(dc5);
dtSample.AcceptChanges();
for (int i = 0; i < 25; i++)
{
DataRow dr = dtSample.NewRow();
for (int j = 0; j < dtSample.Columns.Count; j++)
{
dr[j] = j;
}
dtSample.Rows.Add(dr);
}
dtSample.AcceptChanges();
//GridViewExtension1.ShowHeader = false;
GridViewExtension1.ShowCustomHeader = true;
/*
*=======================================================================
* |Row 1 Cell 1 | Row 1 Col 2 (Span=2) | Row 1 Col 3 |
* | | | |
*=======================================================================
* |Row 2 Cell 1 | | | |
* | | Row 2 Col 2 | Row 2 Col 3 |Row 2 Col 4 |
*=======================================================================
*
*
*
*
* */
// SO we have to make 2 header row as shown above
TableRow TR1 = new TableRow();
TableCell tcR1C1 = new TableCell();
tcR1C1.Text = "Row 1 Cell 1";
tcR1C1.ColumnSpan = 1;
TR1.Cells.Add(tcR1C1);
TableCell tcR1C2 = new TableCell();
tcR1C2.Text = "Row 1 Cell 2";
tcR1C2.ColumnSpan = 2;
TR1.Cells.Add(tcR1C2);
TableCell tcR1C3 = new TableCell();
tcR1C3.Text = "Row 1 Cell 3";
tcR1C3.ColumnSpan = 1;
TR1.Cells.Add(tcR1C3);
GridViewExtension1.CustomHeaderRows.Add(TR1);
TableRow TR2 = new TableRow();
TableCell tcR2C1 = new TableCell();
tcR2C1.Text = "Row 2 Cell 1";
tcR2C1.ColumnSpan = 1;
TR2.Cells.Add(tcR2C1);
TableCell tcR2C2 = new TableCell();
tcR2C2.Text = "Row 2 Cell 2";
tcR2C2.ColumnSpan = 1;
TR2.Cells.Add(tcR2C2);
TableCell tcR2C3 = new TableCell();
tcR2C3.Text = "Row 2 Cell 3";
tcR2C3.ColumnSpan = 1;
TR2.Cells.Add(tcR2C3);
TableCell tcR2C4 = new TableCell();
tcR2C4.Text = "Row 2 Cell 4";
tcR2C4.ColumnSpan = 1;
TR2.Cells.Add(tcR2C4);
GridViewExtension1.CustomHeaderRows.Add(TR2);
GridViewExtension1.DataSource = dtSample;
GridViewExtension1.DataBind();
}
}
Взгляните на эту статью Динамический столбцы столбцов с несколькими столбцами строки
Я хотел выполнить аналогичную задачу, но в качестве заголовка требуются кнопки с возможностью нажатия. Ни один из вышеперечисленных действий не работал в этом случае, поскольку обработчики событий не были подключены (из-за последовательности событий). В конце я использовал тег headertemplate в соответствующем поле шаблона вида сетки. Html выглядит немного более раздутым, но события остаются нетронутыми, без дополнительного кода. Например
<asp:TemplateField >
<HeaderTemplate>
<div>
<div style="text-align: center;padding-bottom: 5px;">
text
</div>
<div>
<asp:Button ID="Button1" runat="server" Text="Apply to all" ToolTip="Apply to all - Special Bolt On" CssClass="sub_button input_btn_5" OnClick="ApplyButton1_Click" />
</div>
</div>
</HeaderTemplate>
<ItemTemplate>....