Click here to Skip to main content
Click here to Skip to main content

The AnywherePlaceHolder. Part 2: The Advanced AnywherePlaceHolder

, 8 Sep 2005
Rate this:
Please Sign up or sign in to vote.
Eliminating the boundaries of frames. Writing your ASP.NET controls on any desired location in any frame.

Example of html page with IFrame. The .aspx page in the IFrame writes controls in it's parent

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 Labels, Tables, GridViews 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 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 Buttons 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 Buttons 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);

    // Searching for internal ASP.NET javascript functions and add 
    // 'SourceFrame.' to the function call.
    for (int j = 0; j < AspNetJavaScriptFunctions.Length; j++)
    {
        destinationHtmlCode.Replace(AspNetJavaScriptFunctions[j], 
            this.SourceFrame + "." + AspNetJavaScriptFunctions[j]);
    }

    // Replacing all 'this.document.' references to the 'SourceFrame.'
    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. Images, Buttons, even complete Tables 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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

DeKale
Web Developer
Netherlands Netherlands
No Biography provided

Comments and Discussions

 
GeneralI don't like frames... PinmemberKastellanos Nikos21-Mar-08 3:27 
Generalsource.style.display = 'none' doesn't work in IE PinmemberDeKale19-Mar-06 1:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 8 Sep 2005
Article Copyright 2005 by DeKale
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid