Earn Cash from forex trading and free 5$ for Regiatation.

Sunday, September 21, 2008

Filtering the XSLT / AJAX WebGrid

Whenever we enable the WebGrid’s XML Load On Demand functionality, this essentially makes use of AJAX requests to fetch the additional rows as they are scrolled into view. Performing other programmatic actions against the Data Source of the Grid such as filtering and sorting requires us to follow some important guidelines so that you will get the results that you expect. This article will show how to allow filtering on the underlying DataView that the WebGrid is bound to.

Whenever we have XML Load On Demand functionality enabled, any posting back will essentially cause the page and the WebGrid to be reset back to the way it was since the first time it was loaded. For example, if the page with the Grid is loaded and the user requests several batches of rows and then performs a full postback, the Grid will be loaded on the page with the same amount of rows that were initially loaded on the first page load. The Web Server is not aware of any additional rows that were fetched with AJAX requests. In the case that we want to allow the user to filter the data that the WebGrid is bound to, you will need to essentially clear the Grid rows explicitly and then rebind to the new result set. You can think of the XML Load On Demand as a form of “Paging” where you have a fixed Data Source and as you scroll through the records, the additional “Pages” are fetched using AJAX requests. The WebGrid needs to have the same exact Data Source each time its _InitializeDataSource event is fired. If you plan on changing the Data Source in any way (Ex: change its schema, change the rows that it contains, etc) you will need to clear the Grid rows and then reassign the Data Source and then DataBind. This will now allow the Grid to work with the new Data Source.


Step-By-Step Example

In this particular implementation, we are going to follow a particular pattern to have the following functionality:

1) The page will load with all records from a particular table
2) The user has the ability to enter text and apply a filter to the Data
3) The page then reloads with the resulting records

To achieve this functionality within a standard grid would be very simple. You would retrieve all of your data the first time and then whenever you need to apply a filter, you would set the filter and then rebind the grid and the page will reload with the new data. With the AJAX functionality enabled, we will need to work with the understanding that the WebGrid uses the InitializeDataSource event to build itself up and create its rows. Whenever applying a filter through server side code, it will be required that the WebGrid rows are all completely removed and then we explicitly assign the DataSource and then call DataBind. Here is the following code to further illustrate what is actually done:

/// Make a property that returns a cached set of Data
///

public WebGrid_AJAX_Filtering_DataView_2005V2_CS.DataSetNorthWind.OrdersDataTable Orders
{
get
{
if (Session["data"] == null)
{
this.sqlDataAdapterOrders.Fill(this.dataSetNorthWind1.Orders);
this.dataSetNorthWind1.Orders.DefaultView.Sort = "CustomerID ASC";
Session["data"] = this.dataSetNorthWind1.Orders;
}

return (WebGrid_AJAX_Filtering_DataView_2005V2_CS.DataSetNorthWind.OrdersDataTable) Session["data"];
}
}

///
/// Give the grid its Data
///

///

///
private void UltraWebGrid1_InitializeDataSource(object sender, Infragistics.WebUI.UltraWebGrid.UltraGridEventArgs e)
{

this.UltraWebGrid1.DataSource = this.Orders.DefaultView;
}

///
/// Whenever we click on this button, we will apply a filter to the DataView.
/// We need to clear the Grid rows and then rebind it explicitly so that the results
/// are shown.
///

///
///
private void Button1_Click(object sender, System.EventArgs e)
{
this.UltraWebGrid1.Rows.Clear();
if (this.TextBox1.Text == "")
{
this.Orders.DefaultView.RowFilter = "";
}
else
{
this.Orders.DefaultView.RowFilter = "CustomerID LIKE '%" + this.TextBox1.Text + "%'" ;
}

this.Label2.Text = this.Orders.DefaultView.Count + " Records Were Found";

this.UltraWebGrid1.DataSource = this.Orders.DefaultView;
this.UltraWebGrid1.DataBind();
}


If you notice, we cache the Orders DataTable in the Session so that the user can work with a particular set of Data. Filtering and sorting can be applied to this cached Data and each time the user applies a filter, the Cached Data is filtered and assigned to the WebGrid. Upon filtering and DataBinding, the WebGrid now has an altered Data Source that will be reloaded with a complete postback. The user can now navigate the new result set by scrolling and causing the AJAX requests to be made against the new result set so that the WebGrid’s InitializeDataSource event can fetch the data that it needs from the Session. This allows a flexible means for the user to work on the Data as well as enjoy the benefit of having the Load On Demand functionality.

Filtering the XSLT / AJAX WebGrid

Whenever we enable the WebGrid’s XML Load On Demand functionality, this essentially makes use of AJAX requests to fetch the additional rows as they are scrolled into view. Performing other programmatic actions against the Data Source of the Grid such as filtering and sorting requires us to follow some important guidelines so that you will get the results that you expect. This article will show how to allow filtering on the underlying DataView that the WebGrid is bound to.

Whenever we have XML Load On Demand functionality enabled, any posting back will essentially cause the page and the WebGrid to be reset back to the way it was since the first time it was loaded. For example, if the page with the Grid is loaded and the user requests several batches of rows and then performs a full postback, the Grid will be loaded on the page with the same amount of rows that were initially loaded on the first page load. The Web Server is not aware of any additional rows that were fetched with AJAX requests. In the case that we want to allow the user to filter the data that the WebGrid is bound to, you will need to essentially clear the Grid rows explicitly and then rebind to the new result set. You can think of the XML Load On Demand as a form of “Paging” where you have a fixed Data Source and as you scroll through the records, the additional “Pages” are fetched using AJAX requests. The WebGrid needs to have the same exact Data Source each time its _InitializeDataSource event is fired. If you plan on changing the Data Source in any way (Ex: change its schema, change the rows that it contains, etc) you will need to clear the Grid rows and then reassign the Data Source and then DataBind. This will now allow the Grid to work with the new Data Source.


Step-By-Step Example

In this particular implementation, we are going to follow a particular pattern to have the following functionality:

1) The page will load with all records from a particular table
2) The user has the ability to enter text and apply a filter to the Data
3) The page then reloads with the resulting records

To achieve this functionality within a standard grid would be very simple. You would retrieve all of your data the first time and then whenever you need to apply a filter, you would set the filter and then rebind the grid and the page will reload with the new data. With the AJAX functionality enabled, we will need to work with the understanding that the WebGrid uses the InitializeDataSource event to build itself up and create its rows. Whenever applying a filter through server side code, it will be required that the WebGrid rows are all completely removed and then we explicitly assign the DataSource and then call DataBind. Here is the following code to further illustrate what is actually done:

/// Make a property that returns a cached set of Data
///

public WebGrid_AJAX_Filtering_DataView_2005V2_CS.DataSetNorthWind.OrdersDataTable Orders
{
get
{
if (Session["data"] == null)
{
this.sqlDataAdapterOrders.Fill(this.dataSetNorthWind1.Orders);
this.dataSetNorthWind1.Orders.DefaultView.Sort = "CustomerID ASC";
Session["data"] = this.dataSetNorthWind1.Orders;
}

return (WebGrid_AJAX_Filtering_DataView_2005V2_CS.DataSetNorthWind.OrdersDataTable) Session["data"];
}
}

///
/// Give the grid its Data
///

///

///
private void UltraWebGrid1_InitializeDataSource(object sender, Infragistics.WebUI.UltraWebGrid.UltraGridEventArgs e)
{

this.UltraWebGrid1.DataSource = this.Orders.DefaultView;
}

///
/// Whenever we click on this button, we will apply a filter to the DataView.
/// We need to clear the Grid rows and then rebind it explicitly so that the results
/// are shown.
///

///
///
private void Button1_Click(object sender, System.EventArgs e)
{
this.UltraWebGrid1.Rows.Clear();
if (this.TextBox1.Text == "")
{
this.Orders.DefaultView.RowFilter = "";
}
else
{
this.Orders.DefaultView.RowFilter = "CustomerID LIKE '%" + this.TextBox1.Text + "%'" ;
}

this.Label2.Text = this.Orders.DefaultView.Count + " Records Were Found";

this.UltraWebGrid1.DataSource = this.Orders.DefaultView;
this.UltraWebGrid1.DataBind();
}


If you notice, we cache the Orders DataTable in the Session so that the user can work with a particular set of Data. Filtering and sorting can be applied to this cached Data and each time the user applies a filter, the Cached Data is filtered and assigned to the WebGrid. Upon filtering and DataBinding, the WebGrid now has an altered Data Source that will be reloaded with a complete postback. The user can now navigate the new result set by scrolling and causing the AJAX requests to be made against the new result set so that the WebGrid’s InitializeDataSource event can fetch the data that it needs from the Session. This allows a flexible means for the user to work on the Data as well as enjoy the benefit of having the Load On Demand functionality.

WebGrid header text orient vertically instead of horizontally

The HTML rendered for the display of the HeaderText can be modified to reorient vertically by adding a DIV tag to the HeaderText of the column.

To show the HeaderText of a column vertically oriented you would need to modify the HeaderText of the column. As the UltraWebGrid eventually renders down as HTML, modification of the HTML elements, or adding new HTML elements as is the case in this sample, enhances the customizable look and feel of the UltraWebGrid.

This solution is based off of IE6+ and will render normally in most other browsers as the attributes on the DIV tag will be ignored.

e.Layout.Bands[0].Columns.FromKey("Active").HeaderText = "

" + e.Layout.Bands[0].Columns.FromKey("Active").HeaderText + "
"
e.Layout.Bands[0].Columns.FromKey("Active").Width = Unit.Pixel(10)

Make a WebGrid cell read-only in certain conditions

Sometimes it is necessary to make a WebGrid cell read-only based on some condition. This article shows how to set a cell as read-only, which can be done on the client-side or server-side.

To do this on the server, set the AllowEditing property of the cell to "AllowEditing.No". On the client, the cell needs to be disabled using the BeforeEnterEditMode client-side event handler.

Server-Side:

In the InitializeRow event, set AllowEditing property to "AllowEditing.No" after checking the condition. In this example, updates are forbidden for cells in the fourth column if the value is already greater than 5000:

private void UltraWebGrid1_InitializeRow(object sender, Infragistics.WebUI.UltraWebGrid.RowEventArgs e)
{
if ((int) e.Row.Cells[3].Value > 5000)
{
e.Row.Cells[3].AllowEditing = Infragistics.WebUI.UltraWebGrid.AllowEditing.No;
}

get rid of scrollbars and set maximum width and height in UltraWebGrid

You can make a WebGrid display with no scrollbars, and fit its height and width to the size of the browser.

this.ultraWebGrid1.Width = Unit.Percentage(100);
this.ultraWebGrid1.Height = Unit.Percentage(100);
this.ultraWebGrid1.DisplayLayout.FrameStyle.CustomRules = "table-layout:auto";

FilterRow functionality in the UltraWebGrid when handling its server-side Click event

When trying to use the UltraWebGrid’s FilterRow functionality, if you are handling its server-side Click event, you will not get the functionality you expect. When a cell in the FilterRow is clicked, the grid posts back, the cell loses focus, and the FilterRow drop down never appears. The way around this is to handle the client-side click event for the grid and cancel the postback if a cell in the filter row is clicked.

First set the UltraWebGrid’s AllowRowFiltering property to OnClient and its FilterUIType property to FilterRow.

UltraWebGrid1.DisplayLayout.Bands[0].FilterOptions.AllowRowFiltering = Infragistics.WebUI.UltraWebGrid.RowFiltering.OnClient;
UltraWebGrid1.DisplayLayout.Bands[0].FilterOptions.FilterUIType = Infragistics.WebUI.UltraWebGrid.FilterUIType.FilterRow;

UltraWebGrid1.DataKeyField = "CustomerID";

hide the AddNew button for some, but not all of the bands in UltraWebGrid

This is possible through some JavaScript code.

The Grid's add new buttons are given IDs as follows:
gridname+_+an+_+band number.

Example:
Grid name=UltraWebGrid1
band=1.
the button Id = UltraWebGrid1_an_1

Therefore, place the following JavaScript block AFTER the grid in the HTML, and your grid will no longer display the band 1 add new button:

place this code inside script tags:

igtbl_getElementById("UltraWebGrid1_an_1").style.display="none";

Code for creating grid dynamically

UltraWebGrid can be created dynamically from code, without being placed on the form at design-time. To accomplish this, a specific constructor must be used which passes in the Id of the control.

To create the grid dynamically, use the following code:


protected Infragistics.WebUI.UltraWebGrid.UltraWebGrid UltraWebGrid1;
UltraWebGrid1 = new Infragistics.WebUI.UltraWebGrid.UltraWebGrid("UltraWebGrid1");
UltraWebGrid1.Columns.Add("col1", "Column 1");
UltraWebGrid1.Columns.Add("col2", "Column 2");
UltraWebGrid1.Columns.Add("col3", "Column 3");

object [] cells = { "Cell1", "Cell2", "Cell3"};
UltraWebGrid1.Rows.Add(new UltraGridRow(cells));
UltraWebGrid1.Rows.Add(new UltraGridRow(cells));
UltraWebGrid1.Rows.Add(new UltraGridRow(cells));
this.Controls.Add(UltraWebGrid1);