Friday, December 5, 2008

Tips for using the RadGrid

Brian Mains continues his overview of the Telerik’s RadGrid Component.

Introduction

Previously, I wrote about using the RadGrid control and how to setup the UI for a simple GridView-like look. In this article, I’m going to talk about some of the tips and tricks that you can give the RadGrid to become more responsive.

Row Clicking

When supporting the ability to select a record in the GridView, the grid needs to have a button that triggers the selection of the row. This causes a postback and sets the selected index of the row, raises an event, and performs some other features. The RadGrid provides this capability using a button as well, but goes a step further. By specifying that the grid can post back on a row click, the row can be selected simply by selecting the row.

Listing 1: Enabling postback on a row click

  1. <tel:RadGrid ID="rgCourses" runat="server" Skin="Web20"
  2. AllowFilteringByColumn="true" onneeddatasource="rgCourses_NeedDataSource"
  3. AllowSorting="true">
  4. <ClientSettings EnablePostBackOnRowClick="true" />
  5. tel:RadGrid>

The ClientSettings property defines a host of client-side features that can be added to the Grid. One of these is the ability to postback upon clicking a row. If setting up that the RadGrid posts back asynchronously (using the RadAjaxManager as previously discussed), the RadGrid’s postback won’t be apparent to the user.

But a postback does occur when the row is clicked, and this fires the RowCommand event called RowClick. For instance, I could use the following code to show an alert, as shown in Listing 2.

Listing 2: Handling a row click

  1. protected void rgCourses_ItemCommand(object source, GridCommandEventArgs e)
  2. {
  3. if (e.CommandName == "RowClick")
  4. {
  5. RadAjaxManager manager = RadAjaxManager.GetCurrent(this.Page);
  6. manager.Alert("Row was clicked!");
  7. }
  8. }

An alert appears to the user to let them know the row was clicked.

Displaying an Empty Message

When displaying an empty message (when no records exist in the underlying data source), it’s nice to have a message appear and let the users know it. This is where the NoRecordsTemplate comes into play:

Listing 3: No Data Template

  1. <MasterTableView AutoGenerateColumns="false" ..>
  2. <NoRecordsTemplate>There isn't any data.NoRecordsTemplate>
  3. MasterTableView>

But to get this template to appear, it requires a few settings. First, the EnableNoRecordsTemplate sets whether theNoRecordsTemplate appears in the first place. If true, if a non-null collection with no records is returned, the template appears. Note what I said; passing null as the data source does not make the no-records template appear.

Sometimes it’s helpful to have the header of the control appear when the no record template appears in the grid. The GridView doesn’t do this at all; it renders a single cell with the empty message only. The RadGrid gives you some options.

Listing 4: The final code for binding no data

  1. <tel:RadGrid ID="rgCourses" runat="server" Skin="Web20"
  2. AllowFilteringByColumn="true" onneeddatasource="rgCourses_NeedDataSource"
  3. AllowSorting="true">
  4. <MasterTableView AutoGenerateColumns="false" EnableNoRecordsTemplate="true"
  5. ShowHeadersWhenNoRecords="false">
  6. <NoRecordsTemplate>There isn't any data.NoRecordsTemplate>
  7. MasterTableView>
  8. <ClientSettings />
  9. tel:RadGrid>
  10. this.rgCourses.DataSource = new object[] {};
  11. this.rgCourses.DataBind();

This produces the following result when no data is entered.

Figure 1: Empty Data Message

Empty Data Message

Editing Data

Editing data works similarly to the GridView, with a noticeable difference. There are different ways to edit the data. For instance, instead of changing the row to edit in the current row, the Telerik RadGrid control edits data using a form beneath the row. This is due to the EditForms setting for the EditMode property of the MasterTableViewproperty. Take a look at the example below:

Figure 2: Editing in a separate form

Editing in a separate form

This can be changed however; editing can occur in place by changing the EditMode property to InPlace.

Listing 5: Setting the EditMode

  1. <MasterTableViewEditMode="InPlace">

Changing to in-place editing uses a more familiar GridView-like result shown below.

Figure 3: In-Place editing

In-Place editing

A third option is to use the PopUp option; this option pops up a new window that the user can use to edit the information outside of the context of the grid altogether.

To generate the edit button you see above (edit turns to update and cancel just like the GridView does whenever editing is invoked), there are two ways to do this. Turning on AutoGenerateEditColumn at the RadGrid level generates an edit column, as well as using the GridEditCommandColumn class. I opted for the latter approach, as shown in Figure 6.

Listing 6: Generating an update column

  1. <tel:GridEditCommandColumn EditText="Update" UniqueName="Update" />

Accessing Rows and Cells

The RadGrid uses the same underlying table structure that the GridView uses, which is the logical choice considering the layout of the user interface. Each row is of the type GridItem; however, its actual underlying representation is GridDataItem or GridEditableItem. This is because the GridItem class is the base class for each of these classes; the GridDataItem represents a read-only data bound item view, whereas the GridEditableItem represents an item currently being edited.

When accessing data (like in ItemDataBound), the event argument’s Item property (represented by the GridItem class) can be cast to one of these two types. This allows accessing of the cell using the unique name, which isn’t defined in the base class (the base class does have a collection of cells though).

For instance, the style of the abstract column could be changed by using the unique name to get the target cell, then change the italicized setting to true as shown in listing 7.

Listing 7: Setting the abstract column’s font to italic

  1. if (e.Item is GridDataItem)
  2. {
  3. ((GridDataItem)e.Item)["Abstract"].Font.Italic = true;
  4. }

The GridDataItem changes the abstract to italic for each and every row like you would do in the RowDataBound for the GridView; it’s the same concept here. The nice thing about this approach is that the developer isn’t forced to hard-code a positional index to get the cell; they can reference by a unique name.

The row also has some other useful properties/methods. If wanting to figure out if the row is in edit mode (outside of the underlying row type), you can also check out the GridItem’s IsInEditMode property, which is true for a row currently in edit mode. The GridItem class also has an ItemIndex and ItemType properties for determining position and type of row. Interestingly enough, the GridItem also has a RowIndex that determines the index of the row (which could be different than ItemIndex because of the Grid’s header row in the underlying table).

Auto Generated Columns

Both the GridView and the RadGrid have the ability to auto-generate the columns of the grid using the structure from the underlying data source. The RadGrid control maintains a collection of columns for each of the auto-generated columns, using the AutoGeneratedColumns collection in the GridTableView object.

This collection can be important if you want to access column information in the code-behind. Remember above, using the GridDataItem class, I accessed a column called “Abstract”, which used the unique name. The unique name wouldn’t necessarily be known in an auto generation approach. An alternative approach using this collection could be:

Listing 8: Finding an auto-generated column

  1. protected void rgCourses_ItemDataBound(object sender, GridItemEventArgs e)
  2. {
  3. if (e.Item is GridDataItem)
  4. {
  5. GridDataItem dataItem = (GridDataItem)e.Item;
  6. var column = this.rgCourses.MasterTableView.AutoGeneratedColumns.First(i => i.HeaderText == "Abstract");
  7. dataItem[column].Font.Italic = true;
  8. }
  9. }

Using LINQ, the master table view’s generated columns is queried for a column name with the header “Abstract”, the name of the column. In this case, the unique name probably matches the header text, but in case it doesn’t, the method finds a matching header and uses the column to set the italics for.

Conclusion

In this article, we learned a few tricks for working with the RadGrid control, and how to adjust it to add functionality for certain tasks, and how to support working with its object model on the server-side.

No comments: