|   Register   |  
Search  

Building Web Solutions with ASP.NET and ADO.NET

Last Updated 2/3/2009 3:43:00 PM


Abstract


This chapter examines techniques and tools for building sophisticated, professional reports using the DataGrid control in ASP.NET.




INTRODUCTION

The DataGrid control not only is the most versatile reporting tool you have in ASP.NET, but also is likely the only tool you will want to use when building pro-fessional reports. In the previous chapters, I reviewed the basic set of features and functionalities supplied by the control. Although the DataGrid control is useful in many circumstances, you still need to write a lot of code (mostly smart and tricky code) to build complex solutions.

The DataGrid control deliberately mimics the interface and behavior of a Microsoft Excel worksheet, so programmers like you expect it to provide the same level of functionality. Microsoft was just whetting your appetite when it developed the control's object model, however, because you can actually do so much more with it than is immediately apparent from scanning its supported methods and events. In this chapter, you will learn a bunch of practical solu-tions and tips that take advantage of the object model. So far, we've only just touched on the concepts that we will explore in the following pages: item selection and information drill-down.


ITEM SELECTION

If you need a grid of data, you probably also need a way to let your users select a particular row of that grid and see related information. I already touched on this topic in Chapter 1 when I discussed the selection mechanism for the DataList control. Let's see how it works for the DataGrid control.

The internal mechanism for selection when using the DataGrid control is nearly identical to the one you saw in action for the DataList control. Typically, users trigger the selection by clicking a column button with the CommandName attribute set to the keyword select. The same event can also occur pro-grammatically when the SelectedItemIndex property of the DataGrid control is set to a value greater than -1.

A selected row can have a custom style that you specify by using the SelectedItemStyle property; however, columns (including templated columns) do not support a particular template for a selected item, such as the DataList control's SelectedItemTemplate template. Only one row in the DataGrid control can be selected at any time. Multiple selection is not supported. Later in this chapter I'll show you how to work around this limitation.

NOTE: A row is selected only if the user clicks the column button associated with the Select command. Full row selection is not supported. There is an architectural issue behind this limitation. To pro-cess the selection event on the server, you need an interactive element on the page that, when clicked, posts back to the server. Only link but-tons allow for this, unless you write some ad-hoc JavaScript client-side script code.

Enabling Item Selection


To enable declarative (as opposed to programmatic) selection, you need to have in the DataGrid control a button column with the CommandName property set to select.

<asp:ButtonColumn Co andName="select" HeaderText="Employee"
DataTextField="EmployeeNa e" /> 
The content of the column can be bound to one data source field as well as show static text or even a small picture. When you don't want data bound text, use the Text property instead of DataTextField. (These properties are part of the programming interface of the ButtonColumn class and have nothing to do with the actual selection.) You can place the select column anywhere in the grid and bind it to any column in the data source, just as you can for the EditCommandColumn discussed in Chapter 4.

NOTE: A grid can have as many select columns as needed. Each select column must be created using the ButtonColumn class with the CommandName property set to select. The user can select the row by clicking any of these columns. By making each column in the grid a select column, you can simulate full-row selection.


The DataGrid control treats select command columns in a special way. When the column is clicked, the SelectedIndexChanged event fires to enable you to handle the event. The DataGrid control also applies to the selected row the graphical settings you set by using the SelectedItemStyle property, as the fol-lowing example shows:

<SelectedIteStyle BackColor="blue" /> 
The SelectedIndex property gets and sets the index of the currently selected item. The index is 0'based and refers to the current page, not to the whole data source. The SelectedItem property returns the object that represents the currently selected item. This object is an instance of the class DataGridItem.

TIP: You can obtain the absolute index in the data set of the specified DataGrid control item by using the DataSetIndex property of the DataGridItem class. Each row in the DataGrid control is rendered using an instance of the DataGridItem class, and you access the instance by using the Items collection.

Styling the Selected Row
The selection style has a lower priority than any style settings you explicitly set for the column by using ItemStyle. For example, the following code draws the Position column with a reddish color, and the style is not overridden when the user selects the column:
<asp:BoundColumn runat="server" DataField="title" HeaderText="Position" >
     <item style backcolor="#ffddff" />
</asp:BoundColumn> 
Note that any style attribute set by using ItemStyle or AlternatingItemStyle at the grid level (as opposed to the column level, shown in the preceding code) is overridden during selection. Figure 1 shows what a selected column looks like.

CAUTION: In addition to changing the color of a selected item, you can change the font style to reflect selection. However, when you change the font, the grid can become slightly larger and the text in some cells can wrap to the next line. Also pay attention to the colors you choose. The background color should contrast with both items and alternating items, but avoid too sharp a contrast. When you plan to use selection, don't differentiate items from alternating items too much.

Using Formatted Text
You can use only button columns to enable selection. Button columns can contain only plain data bound text or static text. You cannot apply special tem-plates that mix database fields with special graphical settings, and as I mentioned earlier in this chapter, templated columns do not support an ad-hoc template for selection. You can work around this limitation, however, as Figure 1 shows. The trick is using in-memory columns based on expressions. An expression-based column doesn't take up too much memory because it stores only the metadata of the column plus the expression.

After you retrieve the bindable data, run the following code, which adds a new, customized column. This column embeds in the text any simple HTML formatting you want.

//ds is the DataSet that has just been filled up
DataTable dt =ds.Tables ["MyTable"]; 
DataColumn dc =new
DataColumn("EmployeeName",typeof(String), 
    "titleofcourtesy +'<b>'+lastname +'</b>,'+firstname "); 
dt.Columns.Add(dc); 
This dynamic column is then bound to the select command column.

<asp:ButtonColumn CommandName="select "HeaderText="Employee" 
     DataTextField="EmployeeName "/>
Using Images
You can use small images to identify which column the user can click to select a row. Just set the Text property of the ButtonColumn class with the HTML text that points to the URL of the image.

<asp:ButtonColumn CommandName="select" 
     Text="<img alt='Select 'src=unselected.gif>"/>
For a better graphical result, you might want to explicitly set the border attribute of the <img> tag to 0 and the align attribute to absmiddle. To make the grid even more user friendly, you can make a final refinement and change the bitmap when the row is drawn in selected mode. See Figure 2.

Using the SelectedIndexChanged Event EVENT
When a row is selected, the grid fires the SelectedIndexChanged event. You hook into this event in the usual ASP.NET fashion:

<asp:DataGrid id="grid "runat="server" 
    .
    .
    .
    OnSelectedIndexChanged="SelectionIndexChanged"> 
You write a handler for SelectedIndexChanged only when you need to accomplish tasks in response to the row selection'for example, changing the bitmap to reflect selection. You don't need the handler to draw the row in selected mode.

public void SelectionIndexChanged(Object sender,EventArgs e) 
{ 
    SelectRecord(); 
}
The SelectedIndex and SelectedItem properties let you know about the selected item. To retrieve the DataRow object that produced the current DataGrid item, you can leverage the combined effect of the DataKeyField and DataKeys properties. As discussed in previous chapters, you set DataKeyField with the name of a field that accepts unique values, and DataKeys gathers those key values. You select an entry within the collection by using the index returned by SelectedIndex. The following code shows how to retrieve the key value for the selected row:

public void SelectRecord() 
{ 
    int nEmpID =(int)grid.DataKeys [grid.SelectedIndex ]; 
    DataRow dr =RetrieveRowByID(nEmpID); 
}
When the SelectedIndexChanged event fires, the SelectedIndex property is guaranteed to be up-to-date.

The select command column is a button column, so you would expect it to fire the ItemCommand event when clicked. This is exactly what happens. With tracing enabled, notice that, as shown in Figure 3, the ItemCommand event arrives first, before the SelectedIndex property is updated.

When ItemCommand fires, SelectedIndex contains the index of the previously selected row.

Selecting Rows Programmatically


In principle, to select a row, you don't need a select command column. Although clicking a cell is the most intuitive way for a user to make a selection, you could select rows programmatically, regardless of whether a specific command column is present. To select a row programmatically, you set the SelectedIndex property to the 0'based index that corresponds to the position of the row in the current page. You cannot select a row that belongs to another page, but if you assign to SelectedIndex a value higher than the number of items in the page, no exception is thrown.

NOTE: When you programmatically select or deselect a row, neither ItemCommand nor SelectedIndexChanged is fired. Since no event occurs, your code is responsible for maintaining the consistency of the application's state. For example, you can simulate the events by calling directly the subroutines the event handler would execute.

Deselecting the Selected Row
The DataGrid control does not provide an interactive way to deselect the currently selected row. You can do that only programmatically by setting the SelectedIndex property to -1. This operation will not fire any event to the page.

Can you remove the selection automatically and interactively? The intuitive approach would be to enable the user to deselect the row by clicking the row a second time'one click selects, and two consecutive clicks restore the original state. But this functionality is impossible for a simple reason: when the DataGrid control is rendered with a selected row, the cell of the select column is not clickable and cannot post back for a selection change event. The workable approach is to provide the page with a link button.

<asp:linkbutton runat="server "id="btnUnselect "enabled="false "
    text="Unselect "onclick="OnUnselectRecord "/> 
The link button is disabled or invisible until a row is selected. The state of the link button can be easily managed by using the SelectedIndexChanged event or any other code that runs after a selection is made. The link's onclick event will then deselect the row programmatically.

NOTE: With a pageable DataGrid control, the selected index is maintained across pages. For example, if row 3 is selected on page 1 and the user moves to page 2, by default row 3 will also be selected on the new page. If the new page has fewer rows than the row number initially selected (in our example, fewer than 3 rows), no row is selected. This is default behavior. To work around it, cancel the selection in the PageIndexChanged event.




Page: 1, 2, 3, 4

next page

Rate this:
Recent Comments
There are currently no comments. Be the first to make a comment.