Reputation: 2201
How do I add a colgroup tag to the datagrid control so that I can style each column using css?
Upvotes: 3
Views: 3983
Reputation: 245
To do a COLGROUP tag I used the Render method. This works well because it's fast and does minimal string manipulation. I started with what's below tweaking widths as needed. The browser will expand columns if too narrow. What this does is produce the minimum width for each.
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
If Not Response.IsClientConnected Then Exit Sub
writer.InnerWriter.Close()
writer.InnerWriter = New IO.StringWriter
MyBase.Render(writer)
Dim buf$ = writer.InnerWriter.ToString
Dim p As Integer = buf.IndexOf("<thead>")
If p < 0 Then
Response.Write("CANNOT FIND THEAD TAG")
Exit Sub
End If
Response.Write(buf.Substring(0, p))
Response.Write("
<colgroup>
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
<col style='width:100px;' />
</colgroup>
")
Response.Write(buf.Substring(p))
End Sub
Upvotes: 0
Reputation: 31
I've searched for some days for a solution on how to add ColGroup template to a GridView. Using the answer given by Josh uphere, and a couple of days of reading about derived objects, especially GridView, I thought that an updated and working solution would help people around.
Imports System.ComponentModel
Imports System.Web.UI
Imports Microsoft.VisualBasic
Imports System.IO
Namespace CustomControls
<ToolboxData("<{0}:GridViewColGroup runat=server></{0}:GridViewColGroup>")> _
<System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust"), _
ParseChildren(True)> _
Public Class GridViewColGroup
Inherits GridView
Implements INamingContainer
Private _ColGroup As ColGroup = Nothing
Private _ColGroupTemplate As ITemplate = Nothing
<Browsable(False), _
Description("The ColGroup template."), _
TemplateContainer(GetType(ColGroup)), _
PersistenceMode(PersistenceMode.InnerProperty)> _
Public Overridable Property ColGroupTemplate() As ITemplate
Get
Return _ColGroupTemplate
End Get
Set(ByVal value As ITemplate)
_ColGroupTemplate = value
End Set
End Property
<Browsable(False), _
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Property ColGroup() As ColGroup
Get
Me.EnsureChildControls()
Return _ColGroup
End Get
Set(ByVal value As ColGroup)
_ColGroup = value
End Set
End Property
Protected Overrides Sub CreateChildControls()
MyBase.CreateChildControls()
_ColGroup = New ColGroup()
If Not ColGroupTemplate Is Nothing Then
ColGroupTemplate.InstantiateIn(_ColGroup)
End If
Me.Controls.Add(_ColGroup)
End Sub
Protected Overrides Sub Render(ByVal writer As HtmlTextWriter)
EnsureChildControls()
' Get the base class's output
Dim sw As New StringWriter()
Dim htw As New HtmlTextWriter(sw)
MyBase.Render(htw)
Dim output As String = sw.ToString()
htw.Close()
sw.Close()
' Insert a <COLGROUP> element into the output
Dim pos As Integer = output.IndexOf("<tr")
If pos <> -1 AndAlso _ColGroup IsNot Nothing Then
sw = New StringWriter()
htw = New HtmlTextWriter(sw)
_ColGroup.RenderPrivate(htw)
output = output.Insert(pos, sw.ToString())
htw.Close()
sw.Close()
End If
' Output the modified markup
writer.Write(output)
End Sub
End Class
<ToolboxItem(False)> _
Public Class ColGroup
Inherits WebControl
Implements INamingContainer
Friend Sub RenderPrivate(ByVal writer As HtmlTextWriter)
writer.Write("<colgroup>")
MyBase.RenderContents(writer)
writer.Write("</colgroup>")
End Sub
End Class
End Namespace
This really offers you the opportunity to use it as Josh sais:
<aspcust:GridViewColGroup runat="server" ID="gridName">
<ColGroupTemplate>
<col class="some_class_1" />
<col class="some_class_2" />
...
<col class="some_class_n" />
</ColGroupTemplate>
<Columns>
...
</Columns>
</aspcust:GridViewColGroup>
if you wrap the derived class into a namespace and register it in the web.config as follows:
<configuration>
<system.web>
<pages>
<controls>
<add tagPrefix="aspcust" namespace="CustomControls" />
</controls >
</pages >
</system.web>
</configuration>
Programatically, you can add a new column into ColGroup at, let's say, PreRender:
Protected Sub gridName_PreRender(ByVal sender As Object, ByVal e As System.EventArgs)
Dim grd As CustomControls.GridViewColGroup = sender
Dim wctrl As New WebControl(HtmlTextWriterTag.Col)
wctrl.CssClass = "some_class_m"
grd.ColGroup.Controls.Add(wctrl)
End Sub
Cheers.
Upvotes: 3
Reputation: 19476
How about a minor change in order to add cols dynamically?
/// <summary>
/// Represents a Col element.
/// </summary>
public class HtmlCol : HtmlGenericControl
{
/// <summary>
/// Default constructor.
/// </summary>
public HtmlCol()
: base("col")
{
}
}
/// <summary>
/// Collection of HtmlCols
/// </summary>
public class HtmlCols : List<HtmlCol>
{
/// <summary>
/// Default constructor.
/// </summary>
public HtmlCols()
{
}
/// <summary>
/// Adds a col to the collection.
/// </summary>
/// <returns></returns>
public HtmlCol Add()
{
var c = new HtmlCol();
base.Add(c);
return c;
}
}
/// <summary>
/// Represents a colgrpup tag element.
/// </summary>
internal class ColGroup : WebControl, INamingContainer
{
internal void RenderPrivate(HtmlTextWriter writer)
{
writer.Write("<colgroup>");
base.RenderContents(writer);
writer.Write("</colgroup>");
}
internal void RenderPrivate(HtmlTextWriter writer, HtmlCols cols)
{
writer.Write("<colgroup>");
base.RenderContents(writer);
foreach (var c in cols)
{
c.RenderControl(writer);
}
writer.Write("</colgroup>");
}
}
[ToolboxData("<{0}:PlainGrid runat=server></{0}:Table>")]
public class PlainGrid : GridView
{
private ColGroup _colGroup = null;
private ITemplate _colGroupTemplate = null;
private HtmlCols _cols = null;
[TemplateContainer(typeof(ColGroup))]
public virtual ITemplate ColGroupTemplate
{
get { return _colGroupTemplate; }
set { _colGroupTemplate = value; }
}
protected override void CreateChildControls()
{
base.CreateChildControls();
if (ColGroupTemplate != null)
{
ColGroupTemplate.InstantiateIn(_colGroup);
}
}
protected override void Render(HtmlTextWriter writer)
{
// Get the base class's output
var sw = new StringWriter();
var htw = new HtmlTextWriter(sw);
base.Render(htw);
string output = sw.ToString();
htw.Close();
sw.Close();
// Insert a <COLGROUP> element into the output
int pos = output.IndexOf("<tr");
if (pos != -1 && _colGroup != null)
{
sw = new StringWriter();
htw = new HtmlTextWriter(sw);
_colGroup.RenderPrivate(htw, _cols);
output = output.Insert(pos, sw.ToString());
htw.Close();
sw.Close();
}
// Output the modified markup
writer.Write(output);
}
/// <summary>
/// Gets/Sets col items.
/// </summary>
public HtmlCols Cols
{
get { return _cols; }
set { _cols = value; }
}
/// <summary>
/// Default constructor
/// </summary>
public PlainGrid()
{
base.AutoGenerateColumns = false;
_colGroup = new ColGroup();
_cols = new HtmlCols();
}
}
Upvotes: 0
Reputation: 82513
I thought this was addressed in .NET 3.5, but I can't find any references. Anyways, here is a hand-rolled server control that allows you to specify colgroup
...
public class ColGroupGridView : GridView
{
private ColGroup _ColGroup = null;
private ITemplate _ColGroupTemplate = null;
[TemplateContainer(typeof(ColGroup))]
public virtual ITemplate ColGroupTemplate
{
get { return _ColGroupTemplate; }
set { _ColGroupTemplate = value; }
}
protected override void CreateChildControls()
{
base.CreateChildControls();
_ColGroup = new ColGroup();
ColGroupTemplate.InstantiateIn(_ColGroup);
}
protected override void Render(HtmlTextWriter writer)
{
// Get the base class's output
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
base.Render(htw);
string output = sw.ToString();
htw.Close();
sw.Close();
// Insert a <COLGROUP> element into the output
int pos = output.IndexOf("<tr");
if (pos != -1 && _ColGroup != null)
{
sw = new StringWriter();
htw = new HtmlTextWriter(sw);
_ColGroup.RenderPrivate(htw);
output = output.Insert(pos, sw.ToString());
htw.Close();
sw.Close();
}
// Output the modified markup
writer.Write(output);
}
}
internal class ColGroup : WebControl, INamingContainer
{
internal void RenderPrivate(HtmlTextWriter writer)
{
writer.Write("<colgroup>");
base.RenderContents(writer);
writer.Write("</colgroup>");
}
}
Use it like this...
<custom:ColGroupGridView ... runat="server">
<ColGroupTemplate>
<col class="itemid" />
<col class="cover-image" />
<col class="title" />
<col class="number" />
<col class="year" />
<col class="rating" />
<col class="cgc-rating" />
<col class="description" />
</ColGroupTemplate>
<!-- Rest of stuff here... -->
</custom:ColGroupGridView>
Source: Jeff Prosise's Blog
Upvotes: 6