Knowledgebase
Customizing the ASP.NET Grid contents
Posted by Vladimir Lyutetsky on 17 April 2008 05:29 PM

This article discusses customizing HTML OLAP Grid contents. Read the article on the Ria OLAP Grid customization here.

This article applies to:

  • RadarCube ASP.NET Direct
  • RadarCube ASP.NET for MS Analysis

 


Basics
Abridging text in the cell
Formatting Cells in the Data Area
Placing Images into a Cell
Placing HTML & ASP.NET Server Controls

This article deals with the most frequently asked questions about changing, formatting and abridging the contents of the Grid cells, adding hyperlinks, images and buttons.

Basics

Any change of a Grid cell contents is done in the TOLAPGrid.OnRenderCell event handler1. This event allows the default contents of any cell to be replaced with any HTML-code. This means, whatever we want to appear in the cell the only thing we really need to do is to make a valid HTML-code and assign it as the "Text" property of the object which is passed to this event as a parameter.

For example, let's replace the Grid cell contents with a red inscription "My Text":

protected void TOLAPGrid1_OnRenderCell(TOLAPGrid sender, RenderCellEventArgs e)
{
e.Text = "<font color=\"red\">My Text</font>";
}

Of course, this example only serves to illustrate the basic idea of our method and is not applicable in real life "as is". Below we will discuss more appropriate cases.

Abridging text in the cell

If a Grid cell shows a too long text it may not look too good and even cause inconvenience for a user. For instance:

Doesn't look too good, don't you agree?

It would be much better to abridge the text in the cell, leaving only the first symbols, with the opportunity to see the full text when hovering the mouse over the cell. It can be done by placing the abridged text into the "Span" tag and the full one into the "Title" attribute:

<span title="uncutted text">cutted...</span>

Making TOLAPGrid.OnRenderCell event handler we get the following:

protected void TOLAPGrid1_OnRenderCell(TOLAPGrid sender, RenderCellEventArgs e)
{
if (e.Text.Length > 25)
{
string cutted = e.Text.Substring(0, 21) + "...";
string uncutted = e.Text;

e.Text = "<span title=\"" + uncutted + "\">" + cutted + "</span>";
}
}

Formatting Cells in the Data Area

Objective: to format the Grid cells contents2:

We need to format the cells in the "Sales Amount" measure as currency values, and "Order Count" as group-delimited integers, using German regional settings. To do so we'll use the following event handler:

protected void TOLAPGrid1_OnRenderCell(TOLAPGrid sender, RenderCellEventArgs e)
{
IDataCell dc = e.Cell as IDataCell;
if ((dc != null) && (dc.Data != null))
{
if ((dc.Address.Measure != null) && (dc.Address.Measure.DisplayName == "Sales Amount"))
{
e.Text = Convert.ToDecimal(dc.Data).ToString("c", new CultureInfo("de-DE").NumberFormat);
}

if ((dc.Address.Measure != null) && (dc.Address.Measure.DisplayName == "Order Count"))
{
e.Text = Convert.ToDecimal(dc.Data).ToString("n0", new CultureInfo("de-DE").NumberFormat);
}
}
}

The Grid then will look like this:

Placing Images into a Cell

Placing images into a Grid is much like abridging a text. For instance, we need to place the "Negative.gif" image into a cell if it contains a negative value, if the value is positive the "Positive.gif" should appear:

protected void TOLAPGrid1_OnRenderCell(TOLAPGrid sender, RenderCellEventArgs e)
{
IDataCell dc = e.Cell as IDataCell;
if (dc != null)
{
string alt = e.Text;
string imageName = (Convert.ToDouble(dc.Data) > 0) ? "images/positive.gif" : "images/negative.gif";

e.Text = "<img src=\"" + imageName + "\" alt=\"" + alt + "\" />";
}
}

What we get as a result will look something like this:

Placing HTML & ASP.NET Server Controls

Placing a "non-event" HTML-control into a Grid cell should not cause you any difficulty: we have just described placing <span> and <gif> tags. However, if we want to handle some event for the placed control on the server (like pressing a button, for instance), there are a lot of niceties to be taken into consideration.

A standard decision, like

Button b = new Button();
b.ID = "MyButton";
b.Click += MyClick;
TOLAPGrid1.Controls.Add(b);

won't work here. You won't even see your control in the cell. Why? For the cell contents to be changed we need to change the e.Text property of the OnRenderCell event, as we did in all previous cases.

We can use the RenderControl method of the placed control:

StringWriter cw = new StringWriter();
HtmlTextWriter writer = new HtmlTextWriter(cw);
b.RenderControl(writer);
e.Text = cw.ToString();

Now we will see our control in the cell. But, unfortunately, even in this case the "MyClick" server handler won't be called on. Not going into too much detail we'll point out that this is due to particular qualities of all the ASP.NET controls' infrastructure: if you want them to operate correctly, you have to create them and then place into the "Controls" container's collection in Page_Init page handler, not later. Otherwise the various bugs are likely to occur with the added controls (depending on how complex your controls are), the least of which is not being able to fire the server event handler. Moreover, any control, even the one correctly created in Page_Init handler, may be placed on a web page not more than once. And what if your Grid has more than one cell?

So, what do we do? There are two ways:

  1. To create ASP.NET controls, add them to TOLAPGrid.Controls collection and assign them server handlers in the Page_Init method, then render them in OnRenderCell event handler, minding how many controls you have already placed on your web page.
  2. To place usual HTML controls into Grid cells assigning their client JScript events functions initiating the handling of these events on the server.

The second way is the most applicable, so we'll discuss it in detail:

Objective:

By clicking the cell we need to fire the DoCellClick server handler and pass an ICell instance to it as a parameter describing the chosen cell.

To do so we need:

  1. In OnRenderCell event we place HTML-controls in all the Grid cells with the call of a Postback-function with the clicked cell's coordinates as their onclick JScript event.
  2. Implement the IPostBackEventHandler interface in the web page, thus making it a receiver of Postback-events.
  3. With the given coordinates, we'll get an ICell object in the Postback-event handler and pass it to the DoCellClick method.
public partial class _Default : System.Web.UI.Page, IPostBackEventHandler
{
protected void TOLAPGrid1_OnRenderCell(TOLAPGrid sender, RenderCellEventArgs e)
{
HtmlButton b = new HtmlButton(); // an html button to place it in the cell
b.InnerText = e.Text; // assing the text on the button

int row = e.Cell.StartRow; //row cell index
int column = e.Cell.StartColumn; //column cell index

// Get the JScript function fulfilling the postback action. The parameter string contains
// the 'click' marker and the coordinates of clicked cell to parse them
// in the IPostBackEventHandler.RaisePostBackEvent method
string s = ClientScript.GetPostBackEventReference(this, "click|" + row.ToString() + "|" + column.ToString());

// assign this function as a handler to the button.onclick jscript event
b.Attributes.Add("onclick", s);

// render the button
StringWriter cw = new StringWriter();
HtmlTextWriter writer = new HtmlTextWriter(cw);
b.RenderControl(writer);
e.Text = cw.ToString();
}

#region IPostBackEventHandler Members

void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
{
// if the postback action raises by clicking the any grid cell button
if (eventArgument.StartsWith("click"))
{
// parse the parameter string
string [] s = eventArgument.Split('|');
int row = Convert.ToInt32(s[1]); // row cell index
int column = Convert.ToInt32(s[2]); // column cell index
// give the ICell instance
ICell cell = TOLAPGrid1.CellSet.Cells(column, row);
// call the MyClick method
MyClick(cell);
};
}

#endregion

void MyClick(ICell cell)
{
// do something
}
}

If we just need to handle a click by cell's contents on the server, then we'd better use the "Span" tag instead of "Button" object, and use its onclick event in the same way.

The similar way can be used if we want to handle a Callback-event on a cell click. For that we need to implement the ICallbackEventHandler on the page.

Now, if we keep on discussing the more and more complex examples, we'll be straying too far from basics of the RadarCube operations in favor of academic study of ASP.NET infrastructure, which is a bit different from what we set out to do. So, it's high time we stopped here.


1 In the Evaluation version this event handler cannot be fired for the first nine cells of the data area.

2 The formatting method presented below is universal but not the most effective. The same result can be achieved by a simple change of format masks for measure on MS AS server (for MS AS version) or value of the TMeasure.DefaultFormat property (for Direct version).

(1031 vote(s))
This article was helpful
This article was not helpful

Help Desk Software by Kayako Resolve