Introduction
When writing accessible websites, we are told that frames are wrong. But with web-applications for the local intranet of your company or your customers, frames can be very useful. But why is it that we ASP.NET developers rarely use frames for our web-applications? Not because we don't like frames, but because ASP.NET limits us to the page we are currently building, disallowing us to reach out of our 'frame' and altering other frames, without refreshing them constantly.
This article is part two of a trilogy, in which I present the AnywherePlaceHolder
. A control that functions like a normal PlaceHolder
(with children), but that enables you to render the child controls in any frame of your web-application. The control is built in the new ASP.NET 2.0 and uses generics and is deeply coupled with the ASP.NET 2.0 client side JavaScript functions.
If you did not read the first part of this article, I'd advice you to read that first: The AnywherePlaceHolder. Part 1: The Simple AnywherePlaceHolder.
In the first part of this article, I presented the BaseAnywherePlaceHolder
and the SimpleAnywherePlaceHolder
. The SimpleAnywherePlaceHolder
was only used to explain the basics of the real AnywherePlaceHolder
that will now be explained in part 2. The SimpleAnywherePlaceHolder
can write normal controls like Label
s, Table
s, GridView
s to any desired frame.
In this part, I will explain the working of the AnywherePlaceHolder
that enables you to write basically any content, including submit buttons, to any other frame, with respect to their functionality. Even JavaScript code will still work.
In part three, I will explain the working of the AnywhereValidationSummaryPlaceHolder
. This is a AnywherePlaceHolder
with the functionality of a normal ValidationSummary
. This is a BaseAnywherePlaceHolder
with the functionality of a normal ValidationSummary
. This special PlaceHolder
allows you to write your custom messages and validation error messages into the frame of choice.
ASP.NET 2.0
This project is written for ASP.NET 2.0, and will not compile under .NET 1.x. However I believe that it can be ported back to .NET 1.x, with a little bit of effort.
Using the code
In this part, we'll be examining the AnywherePlaceHolder
class. Below is the class diagram.
The AnywherePlaceHolder
solves the problems with JavaScript and submit buttons, that the SimpleAnywherePlaceHolder
had. First of all, the AnywherePlaceHolder
searches its own control hierarchy to find Button
controls that have their UseSubmitBehaviour
property enabled. Submit buttons are real nasty animals when injecting code. Logically, because the submit behavior of a Button
has no effect, without a Form
element. So what we must do is set the UseSubmitBehaviour
of all Button
s to false
before we buffer the child controls' HTML code.
The submit has also a really important feature. A Form
can force a submit when return is pressed within an input control on the page. This allows the user to use the page without the mouse. So when we remove the Button
s from the source this feature will disappear. Iterating all child controls is done with the ControlTree
class. Explaining this class is beyond the scope of this article. Download the source code and see how this is implemented.
The solution for this is rather simple. Render the Button
controls normally in the source frame with their "submit" behavior enabled, but hide them using the stylesheet 'display
' property. Remember the source.style.display = 'none';
line from part one?
Okay, now we fixed the problem with the submit buttons, but still no button will work, because every ASP.NET Button
uses JavaScript by default. The buttons are rendered in the destination frame, but must call the JavaScript functions in the source frame. For this we need the SourceFrame
property in the BaseAnywherePlaceHolder
class. The AnywherePlaceHolder
's method ConvertSourceCode
does the trick. This method simply searches for predefined JavaScript functions from the ASP.NET 2.0 framework and adds the sourceframe before it. The ConvertSourceCode
method is noted below:.
protected static readonly string[] AspNetJavaScriptFunctions = new string[] {
"WebForm_CallbackComplete"
, "WebForm_DoCallback"
, "WebForm_DoPostBackWithOptions"
, "WebForm_EncodeCallback"
, "WebForm_FireDefaultButton"
, "WebForm_GetScrollX"
, "WebForm_GetScrollY"
, "WebForm_InitCallback"
, "WebForm_PostBackOptions"
, "WebForm_ReDisableControls"
, "WebForm_ReEnableControls"
, "WebForm_RestoreScrollPosition"
, "WebForm_SaveScrollPositionOnSubmit"
, "WebForm_SaveScrollPositionSubmit"
, "WebForm_TextBoxKeyHandler"
, "__doPostBack"
};
protected string ConvertSourceCode(string sourceHtmlCode)
{
StringBuilder destinationHtmlCode = new StringBuilder(sourceHtmlCode);
for (int j = 0; j < AspNetJavaScriptFunctions.Length; j++)
{
destinationHtmlCode.Replace(AspNetJavaScriptFunctions[j],
this.SourceFrame + "." + AspNetJavaScriptFunctions[j]);
}
destinationHtmlCode.Replace("this.document.", this.SourceFrame + ".");
return destinationHtmlCode.ToString();
}
As you can see, the method loops through the AspNetJavaScriptFunctions
array and searches for the sixteen defined JavaScript functions. After that it will search for occurrences of this.document.
. The only problem you now still have is calling your own JavaScript functions. The current implementation has no solution for this, but some easy tricks could easily be created.
To wrap things up
You have seen that with minimal coding you can create the AnywherePlaceHolder
that can beam virtually every control from one frame to another with the speed of light. Image
s, Button
s, even complete Table
s can easily be transported between the frames. But as you already know, there is another part of this article, so what is still missing in this concept? Missing is the possibility to put a ValidationSummary
component in another frame. The AnywhereValidationSummaryPlaceHolder
will deal with this in The AnywherePlaceHolder. Part 3: The AnywhereValidationSummaryPlaceHolder!
History
- 22 August, 2005 - Version 1.0. Initial version.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.