developer.com
Search EarthWeb
CodeGuru | Gamelan | Jars | Wireless | Discussions
Navigate developer.com
Architecture & Design  
Database  
Java
Languages & Tools
Microsoft & .NET
Open Source  
Project Management  
Security  
Techniques  
Voice  
Web Services  
Wireless/Mobile
XML  
New
 
Technology Jobs  

   Developer.com Webcasts:
  The Impact of Coding Standards and Code Reviews

  Project Management for the Developer

  Defining Your Own Software Development Methodology

  more Webcasts...




See The Winners!




Developer Jobs

Be a Commerce Partner














 


Related Article -
What Else Can You Do With Version Control?
Working Smarter With ASP.NET 2.0
Quick Debugger Visualizers in Visual Studio 2005
URL Mapping in ASP.NET 2.0
Configuring Your ASP.NET 2.0 Site
Binding to XML Data in ASP.NET 2.0
Developer News -
First Major PHP Update in Years Coming Soon    June 25, 2009
Red Hat CEO Calls on Oracle to Keep Java Open    June 25, 2009
Google Widens AdSense for iPhone, Android Apps    June 24, 2009
Eclipse Galileo Releases 33 Open Source Projects    June 24, 2009
Free Tech Newsletter -

Dynamic Template Columns in the ASP.NET 2.0 GridView Control
By Mike Gunderloy

Go to page: Prev  1  2  

The Test Page

To test this, I banged together a simple ASP.NET page consisting of three controls:

  • A TextBox control named txtQuery
  • A Button control named btnDisplay
  • A GridView control named grdMain. The GridView control has its AutoGenerateColumns property set to False.

The idea is simple: when the user clicks the button, I'll build a new DataTable based on whatever text is entered in the TextBox (so I'm depending on the user to enter a valid SQL query; naturally, in a production application, you'd want to do some error checking!). Then the code will walk through all of the columns of the DataTable and add one dynamic column to the GridView for each DataTable column. Here's how it looks in code:


protected void btnDisplay_Click(object sender, EventArgs e)
{
    // create new DataTable from user input
    string connectionString = 
        "Data Source=localhost;Initial Catalog=AdventureWorks;"
        + "Integrated Security=True";
    SqlConnection conn;
    conn = new SqlConnection(connectionString);
    DataTable dtReport = new DataTable();
    SqlCommand cmd = new SqlCommand(txtQuery.Text);
    cmd.CommandType = CommandType.Text;
    cmd.Connection = conn;
    SqlDataAdapter da = new SqlDataAdapter();
    da.SelectCommand = cmd;
    da.Fill(dtReport);

    // clear any existing columns
    grdMain.Columns.Clear();

    // walk the DataTable and add columns to the GridView
    for (int i = 0; i < dtReport.Columns.Count; i++)
    {
        TemplateField tf = new TemplateField();
        // create the data rows
        tf.ItemTemplate = 
            new GridViewLabelTemplate(DataControlRowType.DataRow, 
            dtReport.Columns[i].ColumnName, 
            dtReport.Columns[i].DataType.Name);
        // create the header
        tf.HeaderTemplate = 
            new GridViewLabelTemplate(DataControlRowType.Header, 
            dtReport.Columns[i].ColumnName, 
            dtReport.Columns[i].DataType.Name);
        // add to the GridView
        grdMain.Columns.Add(tf);
    }

    // bind and display the data
    grdMain.DataSource = dtReport;
    grdMain.DataBind();
    grdMain.Visible = true;
}

The only tricky part is the little bit of plumbing that actually hooks the template class up to the GridView. This is accomplished by creating a new TemplateField object, and telling the TemplateField what template to use for its ItemTemplate and HeaderTemplate (you can set other templates as well, such as the AlternatingItemTemplate and FooterTemplate, and they need not all point to the same template class).

Figure 1 shows the whole thing in action. This version isn't excessively pretty because I stripped it down to just the essentials, but it demonstrates enough that you should be able to add your own formatting back in when you need it.

Building a dynamic GridView

Where Do You Go From Here?

This technique can be extremely powerful when you want to use some of the built-in services of the GridView framework (such as the overall databinding and ability to set cell foreground and background colors) and yet maintain close control over your data. While I can't share much code from our production application with you, I can indicate a couple of the areas where we pushed this technique even further. First, depending on the nature of your data, it may make sense to build special cases within your code to handle particular columns. For example, we've also implemented a hyperlink template column that accepts both text to display and a URL to link to:


public class GridViewHyperlinkTemplate : ITemplate
{
    private DataControlRowType templateType;
    private string columnName;
    private string url;
    private string text;

    public GridViewHyperlinkTemplate(DataControlRowType type, 
        string colname, string URL, string Text)
    {
        templateType = type;
        columnName = colname;
        url = URL;
        text = Text;
    }

    public void InstantiateIn(System.Web.UI.Control container)
    {
        switch (templateType)
        {
            case DataControlRowType.Header:
                Literal lc = new Literal();
                lc.Text = "<b>" + columnName+ "</b>"; 
                container.Controls.Add(lc);
                break;
            case DataControlRowType.DataRow:
                HyperLink hl = new HyperLink();
                hl.Target = "_blank";
                hl.CssClass = "ReportNoWrap";
                hl.DataBinding += new EventHandler(this.hl_DataBinding);

                container.Controls.Add(hl);
                break;
            default:
                break;
        }
    }

    private void hl_DataBinding(Object sender, EventArgs e)
    {
        HyperLink hl = (HyperLink)sender;
        GridViewRow row = (GridViewRow)hl.NamingContainer;
        hl.NavigateUrl = DataBinder.Eval(row.DataItem, url).ToString();
        hl.Text = DataBinder.Eval(row.DataItem, text).ToString();
    }

}

Note that the data binding code for this template sets both the Text and the NavigateUrl of the Hyperlink control. We use this template in some cases where we can recognize patterns in the underlying SQL Server data thanks to naming conventions in our data columns:


for (int i = 0; i < dtReport.Columns.Count;i++ )
{
    // special cases: If SiteName & HomePageURL present, 
    // create hyperlink column
    if (dtReport.Columns[i].ColumnName == "HomePageURL")
    {
        UrlFound = true;
        TemplateField tf = new TemplateField();
        tf.ItemTemplate = 
            new GridViewHyperlinkTemplate(DataControlRowType.DataRow, 
            "Site Name", "HomePageURL", "SiteName");
        tf.HeaderTemplate = 
            new GridViewHyperlinkTemplate(DataControlRowType.Header, 
            "Site Name", "HomePageURL", "SiteName");
        grdReport.Columns.Add(tf);
        continue;
    }
    if ((dtReport.Columns[i].ColumnName == "SiteName") && UrlFound)
        continue;
    // other special cases and general case here ...
}

The other thing to note is that you may also want to get specific formatting on a row-by-row as well as a column-by-column basis. In this case, don't spend a lot of time barking up the template tree! Instead, you'll need to dig into the RowDataBound event of the GridView.

The built-in GridView with automatic column creation can probably handle 95% of your data display needs. But for the other 5%, it's nice to know that these powerful techniques exist. Microsoft's designers didn't think of everything, but in ASP.NET 2.0 they did a lot of work to expose the functionality we need to extend the basic framework, and it's certainly made life a lot easier for those of us working with Web applications.

Click here to download the code.

Mike Gunderloy is the author of over 20 books and numerous articles on development topics, and the Senior Technology Partner for Adaptive Strategy, a Washington State consulting firm. When he's not writing code, Mike putters in the garden on his farm in eastern Washington state.

Go to page: Prev  1  2  


Tools:
Add www.developer.com to your favorites
Add www.developer.com to your browser search box
IE 7 | Firefox 2.0 | Firefox 1.5.x
Receive news via our XML/RSS feed


ASP & ASP.NET Archives






internet.commediabistro.comJusttechjobs.comGraphics.com

Search:

WebMediaBrands Corporate Info

Legal Notices, Licensing, Reprints, Permissions, Privacy Policy.
Advertise | Newsletters | Shopping | E-mail Offers | Freelance Jobs