jump to navigation

Insert a Dynamic Row into a DataGrid August 1, 2007

Posted by codinglifestyle in ASP.NET, C#.
Tags: , , ,
add a comment

DataGrids (v1.1) and GridViews (v2.0) are extremely powerful controls for displaying databound data such as a table from a DB.  They also offer pagination and sorting for free.  However, for all that power at the end of the day they merely render a standard HTML table.  If you’re used to programmatically building your own tables and having special headers/footers or certain rows which behave differently the DataGrid can suddenly feel quite restricting.

 

Usually the place to start when cusomtizing the grid on the fly is the ItemDataBound event.  Here we have access to the DataGridItem and DataRowView representing the specific row being bound.  This allows us to easily test for certain conditions and modify the row.  But this event really limits you to affecting just the row being bound.

 

 

Last week  we needed to insert a new row under certain conditions.  Again, the best place to test if a specific row met these conditions was the ItemDataBound event.  If the condition was met, we wanted to add a row below the current row being bound.  How do we do this?

 

While you have access to the current row’s cells and to the grid itself, there is no obvious way of adding a new row.  The grid’s Items are available but these are bound to our datasource and looks like a dead end.  But they aren’t.  There is a way of adding in a new DataGridItem which translates to adding a new row.  Here’s how you do it:

 

 

    if (bConditionMet)

    {

        //Create an empty DataGridItem

        DataGridItem itemDesc = new DataGridItem(0, 0, ListItemType.Item);

        //This row will show the description of the item being bound

        TableCell cellDesc = new TableCell();

        cellDesc.Text = sDescription;

        cellDesc.ColumnSpan = e.Item.Cells.Count;

        itemDesc.Cells.Add(cellDesc);

        //Add the new row to the table                   

        m_dgItems.Controls[0].Controls.Add(itemDesc);

    }

 

Here we create a new DataGridItem and add cells which can contain text and/or their own controls.  To insert the DataGridItem into the grid is the tricky part.  We grab the first control in the DataGrid which is actually the DataGridTable.  As we are binding row by row the DataGridTable.Controls are filling with DataGridItems.  So, the DataGridTable.Controls only contains the DataGridItems bound thus far.  Hence, when we add our new DataGridItem it is the next row.

 

Advertisements

DataGrid ITemplate TemplateColumn HyperLinkColumn implmenting dynamic URL May 3, 2006

Posted by codinglifestyle in ASP.NET, C#.
Tags: , , , ,
add a comment

Recently I had to replace my HyperLinkColumn on a DataGrid as I was merging data from two datasources and needed to handle a click on the column differently depending on the datasource.  By using a TemplateColumn I reproduced the functionality of a HyperLinkColumn while being able to change the URL depending on the datasource.

TemplateColumn tCol=new TemplateColumn();
tCol.ItemTemplate=new TColumn(sColumn);

dgColumns.Add(tCol);

  public class TColumn: ITemplate
  {
   private string m_sCol;
   public TColumn(string sCol)
   {
    m_sCol   = sCol;
   }

   public void InstantiateIn(Control container)
   {
    HyperLink h = new HyperLink();
    h.DataBinding +=
     new EventHandler(this.OnDataBinding);
    container.Controls.Add(h);
   }

   public void OnDataBinding(object sender, EventArgs e)
   {
    HyperLink h = (HyperLink) sender;
    DataGridItem container = (DataGridItem) h.NamingContainer;
    h.Text = ((DataRowView)container.DataItem)[m_sCol].ToString();

    string sUrl;
    bool bTest;
    //Perform test
    if (bTest)
    {
        sUrl = “http://news.yahoo.com“;
    } else
    {
        sUrl = http://www.cnn.com;
    }
    h.NavigateUrl = sUrl;
    h.Target = “_blank”;
   }
  }

DataGrid ITemplate Columns: Programatically adding columns and wiring events for controls January 10, 2006

Posted by codinglifestyle in ASP.NET, C#.
Tags: , ,
add a comment

One of the great features of the DataGrid is that ability to add ITemplate derived columns which can host any control you like.  For example a column displaying a checkbox or radiobutton can leverage DataGrid’s select feature. It is trivial enough to add a ITemplate column and wire up events in the web designer, but a different story to do so programatically. 

  public class RadioButtonColumn : ITemplate
  {
   private RadioButton m_rb;

   public void InstantiateIn(Control container)
   {
    m_rb = new RadioButton();
    m_rb.AutoPostBack = true;
    m_rb.CheckedChanged +=new EventHandler(m_rb_CheckedChanged);

    container.Controls.Add(m_rb);
   }

   private void m_rb_CheckedChanged(object sender, EventArgs e)
   {
    RadioButton rb = (RadioButton) sender;
    DataGridItem container = (DataGridItem) rb.NamingContainer;
    DataGrid dg = (DataGrid)container.Parent.Parent;
   }
  }

When dynamically adding a ITemplate column to the datagrid control, ITemplate.InstantiateIn will be called when your datagrid is databinding.  So make sure to set up the grid’s columns before you DataBind().  The RadioButtonColumn class will simply display a radio button for each row when added to DataGrid.Columns (DataGrid.AutoGenerateColumns should = false).  However you will notice the event is never fired.

During Page postback the DataGrid.DataBind method will not be called in time to wire up the event because the datagrid columns will be re-created from the ViewState. To make the ITemplate column event’s work place your column into the datagrid before the LoadViewState method is called otherwise ITemplate.InstantiateIn will not be called.  In the ASP.NET lifecycle, LoadViewState method is called before the Load event
and after the Init event, so placing your code into the Init event will wire the event in time to be called.