Click Here to Install Silverlight*
IndiaChange|All Microsoft Sites
MSDN
|Developer Centers|Library|Downloads|How To Buy|Subscribers|My MSDN
 
Solutions to Top Four Questions on DataGrid Web Server Control
By Saravana Kumar
 
Article Posted: May 20, 2003
 

Introduction

The DataGrid Web server control is a powerful tool for displaying information from a data source. It is easy to use; you can display editable data in a professional-looking grid by setting only a few properties. At the same time, the grid has a sophisticated object model that provides you with great flexibility in how you display the data.

This article addresses some of the questions about customizing grid display that are commonly asked in newsgroups, on Web sites, and in other developer forums. The techniques described here are sometimes quite simple and at other times somewhat involved. In each case, however, they address a question of how to go beyond the basic functionality of the DataGrid control.

This articles assumes that you are already familiar with the control — how to add it to a form and configure it to display data. You should also understand how to put a row in the grid into edit mode and other basic tasks. For more details on DataGrid Web Server Control,

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon/html/vbconDataGridWebControl.asp

The Web Forms DataGrid control is not the same as the Windows Forms equivalent. It is a common (and not unreasonable) assumption that they are the same control, or at least have identical functionality. However, the entire programming paradigm for Web Forms is quite different from that for Windows Forms. For example, Web Forms pages perform a round trip to the server for any processing; they must manage state; they feature a very different data-binding model; and so on. This articles addresses only  the issues with Web Forms DataGrid Control.

The Top Four Questions that are addressed in this articles are,

1. Editing and Inserting Multiple Rows at Once.

2. Manipulating DataSource Values while binding to DataGrid

3. DropDownList in Editable DataGrid

4. Showing and Hiding Columns dynamically

Editing And Inserting Multiple Rows at Once

The standard way to edit rows in the DataGrid control — by adding an "Edit, Update, Cancel" button to the grid's columns — only allows users to edit one row at a time. If users want to edit multiple rows, they must click the Edit button, make their changes, and then click the Update button for each row.

In some cases, a useful alternative is to configure the grid so that it is in edit mode by default. In this scenario, the grid always displays editable data in text boxes or other controls; users do not explicitly have to put the grid into edit mode. Typically, users make whatever changes they want and then click a button (not a button in the grid) to submit all changes at once. The page might look something like the following:

To configure the grid for multiple-row edit, add the columns as you normally would and convert all editable columns to template columns. In the Columns tab of the grid's Property Builder, select the column and at the bottom of the window, choose Convert this column into a Template column. To edit the templates, right-click the grid and choose Edit Template.

Add the edit controls to the ItemTemplate. Note that you are not adding them to the EditItemTemplate, as you normally would, because the rows will not be displayed in edit mode. That is, the ItemTemplate will contain editable controls.

Set up data binding for the grid normally. You will need to bind each editable control individually. A typical data binding expression will look like this:

Text='<%# Container.DataItem("Product") %>'

 

Code for DataGrid will be like this,

 

<asp:DataGrid id="DataGrid1" style="Z-INDEX: 101; LEFT: 336px;" runat="server">
<Columns>
       <asp:TemplateColumn HeaderText="Product Name">
            <ItemTemplate>
                  <asp:TextBox id="ProductName" runat="server"  Text =           '<%#Container.DataItem("ProductName") %>'>
                  </asp:TextBox>
              </ItemTemplate>
              ....
              ....
       </asp:TemplateColumn>
</Columns>
</asp:DataGrid>

In this example, it is assumed that DataSource for DataGrid is DataSet. DataSet is created from the XML File. So after doing all the operations, it is saved back to Database. During Save operation with the help of DataKeyField property, we are able to identify whether this record has to be inserted or updated. Since DataKeyField is binded to Primary Key, if it is null then that record has to inserted otherwise we need to update that record.

Private Sub Save_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Save.Click

       Dim di As DataGridItem
       Dim oDataRowcol(1) As DataRow
       Dim dr As DataRow

        'Reading the data from dataSource

        oDataSet.ReadXml("d:\product.xml")

        ' Loop through the items in the datagrid.

        For Each di In DataGrid1.Items

            ' Make sure this is an item and not the header or footer.

       If di.ItemType = ListItemType.Item OrElse di.ItemType =

       If di.ItemType = ListItemType.Item OrElse di.ItemType =

                 ListItemType.AlternatingItem Then

                ' Get the current row for update or insert operations later.

                 If DataGrid1.DataKeys(di.ItemIndex).ToString = "" Then

                    dr = oDataSet.Tables("Product").NewRow

                    ' Insert the row instead.

                    dr("Name") = CType(di.FindControl("ProductName"), TextBox).Text

                    dr("Price") = CType(di.FindControl("ProductPrice"), TextBox).Text

                    dr("Quantity") = CType(di.FindControl("Quantity"), TextBox).Text

                    dr("ProductID") = CType(di.FindControl("ProductID"), TextBox).Text

                    oDataSet.Tables("Product").Rows.Add(dr)

                  Else

                    oDataRowcol = oDataSet.Tables("Product").Select("ProductID =" &

                                                   DataGrid1.DataKeys(di.ItemIndex))

                    ' Update the row instead.

                    dr = oDataRowcol(0)

                    dr("Name") = CType(di.FindControl("ProductName"), TextBox).Text

                    dr("Price") = CType(di.FindControl("ProductPrice"), TextBox).Text

                    dr("Quantity") = CType(di.FindControl("Quantity"), TextBox).Text

                    dr("ProductID") = CType(di.FindControl("ProductID"), TextBox).Text

                   End If

            End If

        Next

       ' Save the changes if there is to database or to any datasource.

        'In this example i am storing it back to XML File

        oDataSet.WriteXml("d:\Product.xml")

    End Sub

Checking for Changed Items

One drawback of the above method of updating and inserting records is  that it is very inefficient to send updates to the DataSet or database for each grid row if there have been only few changes. If you are working with a DataSet, you can add logic to check for changes between the controls in the grid and the corresponding columns in DataSet rows. If you are not using a DataSet — as in the example above — you cannot easily make this comparison, since it would involve a round trip to the database.

A strategy that works for both types of data sources is to establish a way to determine whether rows are "dirty" so you can check that before making an update. The definitive way to determine whether a row has been dirtied is to handle the changed event for the controls in a row. For example, if your grid row contains a TextBox control, you can respond to the control's TextChanged event. Similarly, for check boxes, you can respond to a CheckedChanged event.

If we have one hidden field  for each row in the DataGrid. Then in the handler of these changed events of controls, we can mark that row has changed by changing the value of hidden item. For example if you wants to implement this method, Then create a handler to do this stuff. The following code shows a handler that can be invoked when a TextBox control raises its TextChanged event or when a CheckBox control raises its CheckedChanged event:

    Sub DGRowChanged(ByVal sender As Object, ByVal e As System.EventArgs)

     Dim oControl As Control

        Dim oGenControl As System.Web.UI.HtmlControls.HtmlInputHidden

        oControl = CType(sender, Control)

        oGenControl = oControl.Parent.FindControl("RecordState")

        oGenControl.Value = "Changed"

    End Sub

It is helpful to understand that change events do not, by default, post the page back to the server. Instead, the event is raised only when the page is posted some other way (usually via a Click event). During page processing, the page and its controls are initialized, and then all change events are raised. Only when the change event's handlers have finished is the Click event raised for the control that caused the post.

On to the RowChanged method illustrated above. The code will update that hidden item (RecordState) to “Changed” . This indicates that this record has been changed.

Now the code for save operation will be like this and this method only updates the changed records only. Basically in this method while looping through DataGrid Items we are checking whether that record is changed by checking that hidden field. Then if that record is changed, then do insert or update accordingly.

Private Sub Save_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Save.Click

Dim di As DataGridItem

Dim oDataRowcol(1) As DataRow

Dim dr As DataRow

'Reading the data from dataSource

oDataSet.ReadXml("d:\product.xml")

 

' Loop through the items in the datagrid.

For Each di In DataGrid1.Items

' Make sure this is an item and not the header or footer.

 

 

  If di.ItemType = ListItemType.Item OrElse di.ItemType =

                                             ListItemType.AlternatingItem Then

     ' Get the current row for update or insert operations later.

     If CType(di.FindControl("RecordState"), HtmlInputHidden).Value = "Changed" Then

 

         If DataGrid1.DataKeys(di.ItemIndex).ToString = "" Then

              'Your code for insert goes here

         Else

                     'Your code for update goes here  

         End If

      End If

 

  End If

Next

 ' Save the changes if there is to database or to any datasource.

 'In this example we are storing it back to XML File

 oDataSet.WriteXml("d:\Product.xml")

End Sub

One task is left: binding the handlers to the control events. In Visual Studio, you can only do this in HTML view. The controls are not explicitly instantiated in the code-behind file, so they are not supported by the code tools. Switch the .aspx file to HTML view and in the declarative elements for each of the controls, add the following highlighted syntax:

<asp:TemplateColumn headertext="Product Name">

<ItemTemplate>

             <asp:TextBox id="ProductName" runat="server" OnTextChanged="DGRowChanged"   

                                  Text='<%# Container.DataItem("Name") %>'>

       </asp:TextBox>

</ItemTemplate>

</asp:TemplateColumn>

All the controls can call the same method from their respective change methods, because the signature for both event handlers is the same. That would be true also if you had a list box or drop-down list control, whose SelectedIndexChanged events likewise pass the same arguments

Manipulating DataSource Values while binding to DataGrid

In many situations it is required for us to manipulate the DataSource values while binding to the DataGrid. For example you might store ‘Y’ and ‘N’ as Boolean values in database. But in DataGrid for the properties like Enabled or Checked, it requires Boolean value to be in “True” or “False” format. In this case while binding to DataGrid, you need to change these database values to DataGrid values accordingly. You can do this type of manipulation in two ways.

One way is to write handler for ItemDataBound. The main drawback in this approach is,  ItemDataBound event handler is common to all the DataGridItems. So you need to find out exactly the DataGrid Item in which you needs to do manipulation. Then in that DataGrid Item you need to find out the columns for which you needs to do manipulation. This drawback can be overcome in the other method.

Other way to do this is by writing a function in code behind file, then calling that function while binding in datagrid column by passing the DataSource value as its parameter. Assume that, you wants to enable or disable a “Order” radiobutton in DataGrid based on “Orders Date” column in database. If orders date is not null then you need to enable this radio button otherwise you need to disable this button.

<asp:TemplateColumn headertext="Select Orders">

<ItemTemplate>

      <asp:RadioButton id="RadioButton1" runat="server"

Enabled = '<%# ReturnOrders(DataBinder.Eval(Container.DataItem, "OrdersDate"))  %> '>

       </asp:RadioButton>

</ItemTemplate>

</asp:TemplateColumn>

In the above DataGrid Code, While binding the value of Enabled property of  radio button a function named “ReturnOrder” is called by passing the OrdersDate as one of its parameter. This function will return Boolean value depending upon the OrdersDate. Depending upon this Boolean value this radio button will be enabled or disabled for that record.

Public Function returnSelect(ByVal OrdersDate As String) As Boolean

        If OrdersDate Is DBNull.Value Then

               Return True

        End If

               Return False

 End Function

This is just an simple example on how to manipulate the DataSource values while binding using this method. But you can do use this method in lots of place.

DropDownList in Editable DataGrid

A common request is to present users with a drop-down list when a row is in edit mode. For example, the grid might show a list of orders, including Product Name. When users edit a book record, they might want to assign a different Product; ideally, they can select from a drop-down list that shows possible Products values such as "Onida TV," "LG TV" or "X TV."

Displaying a drop-down list requires a template column in the grid. Typically, the ItemTemplate contains a control such as a data-bound Label control to show the current value of a field in the record. You then add a drop-down list to the EditItemTemplate. In Visual Studio, you can add a template column in the Property builder for the grid, and then use standard template editing to remove the default TextBox control from the EditItemTemplate and drag a DropDownList control into it instead. Alternatively, you can add the template column in HTML view.

After you have created the template column with the drop-down list in it, there are two tasks. The first is to populate the list. The second is to preselect the appropriate item in the list — for example, if the product name is set to X TV," in a order record. when the drop-down list displays, you often want "X TV" to be preselected.

There are many ways to populate the drop-down list like using static items; using records from a dataset; or by using a data reader to read information directly from a database. In this article we are going to see only using records from a Dataset

Populating DropDownList Using DataSet

If the data you want to display in the DropDownList  is a DataSet, you can use simple binding method.  The following shows the declarative syntax. The DropDownList is bound to Product table in DataSet called oDataSet  and ProductId and ProductName are columns in Product Table.

<asp:TemplateColumn HeaderText="Product Name">

   <ItemTemplate>

      <asp:Label id=Label3 runat="server"

          Text='<%# DataBinder.Eval(Container, "DataItem.ProductName") %>'>

      </asp:Label>

   </ItemTemplate>

   <EditItemTemplate>

      <asp:DropDownList id=DropDownList4 runat="server"

         DataSource="<%# oDataSet %>" DataMember="Product"

         DataTextField="ProductName" DataValueField="ProductID" >

      </asp:DropDownList>

   </EditItemTemplate>

</asp:TemplateColumn>

Preselecting an Item in the Drop-Down List

You often want to set the selected item in the drop-down list to match a specific value, usually the value displayed in the cell in display mode. You can do this by setting the SelectedIndex property of the drop-down list to the index of the value to display.

The following example shows a reliable way to do this in a handler for the DataGrid item's ItemDataBound event. This is the correct event to use, because it guarantees that the drop-down list has already been populated, no matter what data source the drop-down list is using.

The trick is in knowing what value to set the drop-down list to. Typically, the value is already available to you either in the current item (being displayed) or in the DataItem property of the current item, which returns a DataRowView object containing the current record. Once you have the value, you can use the DropDownList control's FindByText or FindByValue method to locate the correct item in the list; Then set its selected property to True.

Private Sub DataGrid1_ItemDataBound(ByVal sender As Object, _

      ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) _

      Handles DataGrid1.ItemDataBound

   If e.Item.ItemType = ListItemType.EditItem Then

      Dim drv As DataRowView = CType(e.Item.DataItem, DataRowView)

      Dim currentProduct As String = CType(drv("ProductName"), String)

      Dim ddl As DropDownList

      ddl = CType(e.Item.FindControl("DropDownList1"), DropDownList)

             ddl.Items.FindByText(currentgenre).Selected = True

   End If

End Sub

Showing and Hiding Columns Dynamically

One way to have columns appear dynamically is to create them at design time, and then to hide or show them as needed. You can do this by setting a column's Visible property. The following example shows how to toggle the visibility of the second column (index 1) of the grid:

DataGrid1.Columns(1).Visible = Not (DataGrid1.Columns(1).Visible)

 

©2008 Microsoft Corporation. All rights reserved. Contact Us |Terms of Use |Trademarks |Privacy Statement
Microsoft