5,533,615 members and growing! (16,951 online)
Email Password   helpLost your password?
Platforms, Frameworks & Libraries » .NET Framework » General     Intermediate License: The Common Development and Distribution License (CDDL)

How to harness the power of XHTML and XForms in your .NET applications

By Phil Booth

XForms is an important recommendation from the W3C that enables complex XML-handling applications to be defined in a simple, declarative syntax. This article demonstrates how you can leverage this power in your own applications.
C# (C# 1.0, C# 2.0, C# 3.0, C#), XML, Windows (Windows, TabletPC, Embedded, NT4, Win2K, WinXP, Win2003, Vista), .NET (.NET, .NET 3.5, .NET 3.0, Mono, DotGNU, .NET 1.0, .NET 1.1, .NET 2.0), COM, VS.NET2002, VS.NET2003, VS2005, Visual Studio, Design, Architect, Dev

Posted: 9 Oct 2007
Updated: 5 Dec 2007
Views: 13,203
Bookmarked: 24 times
Announcements
Want a new Job?



Search    
Advanced Search
Sitemap
8 votes for this Article.
Popularity: 3.87 Rating: 4.28 out of 5
1 vote, 12.5%
1
0 votes, 0.0%
2
0 votes, 0.0%
3
1 vote, 12.5%
4
6 votes, 75.0%
5

Screenshot

Introduction

XForms is an important recommendation from the W3C that enables complex XML-handling applications to be defined in a simple, declarative syntax. This article demonstrates how you can harness this technology in your own C# applications. However, the same techniques may be easily applied to other .NET languages, or indeed any programming language that has a COM binding. The XHTML and XForms rendering power at the heart of it all will be provided by formsPlayer, a free XForms processor.

Why XForms?

The advantages of XForms over other solutions have been argued far more eloquently elsewhere than I could manage, so I won't go into great detail here. Instead, those of you interested in reading around the subject in more depth are directed to the links that appear at the foot of this article. To summarise, some of the most salient points, however:

  • XForms documents are device- and platform-independent;
  • XForms uses a declarative syntax, which aids faster development and reduces the potential for bugs when compared to more traditional, procedural approaches;
  • XForms separates data, user interface, and application logic according to the model-view-controller (MVC) design pattern;
  • XForms is an open standard, which means that the same document may be deployed unmodified across all conforming processors;
  • XForms documents are inherently accessible by design;
  • XForms enables comprehensive input validation at the point of entry, reducing the need for server round trips in distributed web applications.

Getting started

Before you can begin, you will need to install formsPlayer, which is freely available, and a reasonably small download. Additionally, pending the resolution of a minor issue in the formsPlayer installer, you'll also need to separately install the Renderer component. Once both of these have been installed, you must import two formsPlayer COM libraries into your C# project via the 'Add Reference' dialog:

  • [Program Files]\Common Files\Sidewinder\Renderer\Renderer4.dll
  • [Program Files]\Common Files\Sidewinder\DOM\DOM2Events.dll

The first of these libraries, the Renderer, provides all of the XHTML and XForms rendering functionality. The second component, an implementation of W3C's DOM Level 2 Events recommendation, facilitates communication between your application, the Renderer, and the live document.

Instantiating the Renderer

Firstly, you must add a new class to your application, representing the window that will host the Renderer. In the article, this class is called RenHost. The initialisation method for this class needs to instantiate and initialise a copy of the Renderer, storing a pointer to its IRender interface:

public class RenHost : System.Windows.Forms.Form
{
    private RendererLib.IRender Renderer;

    ...

    private void RenHost_Load(object sender, System.EventArgs e)
    {
        this.Renderer = (IRender)new RendererLib.RendererClass();
        this.Renderer.Initialise(null);

        ...
    }

    ...
}

Dispatching events

Your application may now customise various characteristics of the Renderer instance, such as setting the handle to its parent window, setting its initial size, or instructing it to propagate any navigation requests out to your application. These properties and many others are all set by dispatching events to the Renderer's IEventTarget interface.

To simplify this process, add a new method to your class along the following lines:

private void DispatchRendererEvent(string sType, int nParam1, int nParam2)
{
    IRendererEvent evt = (IRendererEvent)new RendererEventClass();
    evt.initRendererEvent(sType, false, false, nParam1, nParam2, "");

    IEventTarget tgt = (IEventTarget)this.Renderer;
    tgt.dispatchEvent((DOMEvent)evt);
}

It is not necessary to worry about what all of the different parameters mean at this point. Simply know that the code above allows you to dispatch a renderer event of type sType, along with some event-specific contextual parameters.

Initialising your Renderer instance

The first thing that you will want to do with this new method, then, is to make the Renderer a child of the Panel associated with your RenHost class. This is achieved by dispatching a couple of events during initialisation:

private void RenHost_Load(object sender, System.EventArgs e)
{
    this.Renderer = (IRender)new RendererLib.RendererClass();
    this.Renderer.Initialise(null);

    DispatchRendererEvent("renderer-set-parentwindow",
                          (int)this.PanelRenderer.Handle, 0); 
    DispatchRendererEvent("renderer-set-windowstyle", 2, 0);

    ...
}

The Renderer should also be informed of its initial size and position within its parent, like this:

private void RenHost_Load(object sender, System.EventArgs e)
{
    this.Renderer = (IRender)new RendererLib.RendererClass();
    this.Renderer.Initialise(null);

    DispatchRendererEvent("renderer-set-parentwindow",
                          (int)this.PanelRenderer.Handle, 0); 
    DispatchRendererEvent("renderer-set-windowstyle", 2, 0);

    DispatchRendererEvent("renderer-set-position", 0, 0);
    DispatchRendererEvent("renderer-set-dimensions",
                          this.PanelRenderer.ClientRectangle.Width,
                          this.PanelRenderer.ClientRectangle.Height);

    ...
}

Once these initial window-related properties have been set, you must instruct the Renderer to perform its own window creation:

private void RenHost_Load(object sender, System.EventArgs e)
{
    this.Renderer = (IRender)new RendererLib.RendererClass();
    this.Renderer.Initialise(null);

    DispatchRendererEvent("renderer-set-parentwindow",
                          (int)this.PanelRenderer.Handle, 0); 
    DispatchRendererEvent("renderer-set-windowstyle", 2, 0);

    DispatchRendererEvent("renderer-set-position", 0, 0);
    DispatchRendererEvent("renderer-set-dimensions",
                          this.PanelRenderer.ClientRectangle.Width,
                          this.PanelRenderer.ClientRectangle.Height);

    this.Renderer.InitialiseWindow();

    ...
}

Rendering documents

The Renderer instance is now initialised and ready to render your documents. This, in itself, is a two stage process. First, the document must be loaded in one of three ways:

  • By specifying the location of the document (in RFC 3986 absolute URI format) to LoadURI();
  • By passing a string representation of the markup to LoadXML();
  • By passing a Microsoft IXMLDOMDocument interface pointer to LoadDOM().

Regardless of the method that you use, the document must be well formed, otherwise the load will fail; malformed documents may only be rendered using the supplementary IRenderHTML interface. After the document has been loaded successfully, it can be rendered by the Render() method. You may also pass a fragment identifier and a base URI to this method, if necessary.

So, based on the above, if your application were to contain a browser-style address bar, the Button.Click handler might look something like the following:

private void Button_Click(object sender, System.EventArgs e)
{
    int nFragmentIndex = this.Input.Text.IndexOf('#');
    Uri uri;
    String sFragId;
    if(nFragmentIndex != -1)
    {
        uri = new Uri(this.Input.Text.Substring(0, nFragmentIndex));
        sFragId = this.Input.Text.Substring(nFragmentIndex + 1);
    }
    else
    {
        uri = new Uri(this.Input.Text);
        sFragId = "";
    }
    String sURL = uri.AbsoluteUri;
    String sBase = sURL.Substring(0, sURL.LastIndexOf('/') + 1);

    this.Renderer.LoadURI(sURL);

    this.Renderer.Render(sFragId, sBase);
}

Clearing up

You can continue to load and render as many documents after this as you wish. All that remains is to ensure that you call the Destroy() method before your application terminates:

protected override void Dispose(bool disposing)
{
    if(disposing)
    {
        this.Renderer.Destroy();

        ...
    }

    base.Dispose(disposing);
}

Links

History

  • 09-Oct-2007: Created.
  • 13-Nov-2007: Added separate download information for the Renderer component, pending resolution of an issue in the formsPlayer installer.
  • 05-Dec-2007: Switched license to CDDL, and made some minor cosmetic changes.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)

About the Author

Phil Booth



Occupation: Software Developer
Location: United Kingdom United Kingdom

Other popular .NET Framework articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 24 of 24 (Total in Forum: 24) (Refresh)FirstPrevNext
Subject  Author Date 
Questionevent-based communication between the document and the appmemberabel_b7:11 15 Apr '08  
AnswerRe: event-based communication between the document and the app [modified]memberPhil Booth23:45 15 Apr '08  
GeneralRe: event-based communication between the document and the appmemberabel_b10:29 16 Apr '08  
GeneralRe: event-based communication between the document and the appmemberPhil Booth1:19 17 Apr '08  
GeneralRe: event-based communication between the document and the appmemberabel_b8:08 17 Apr '08  
GeneralRe: event-based communication between the document and the appmemberPhil Booth1:29 18 Apr '08  
GeneralRe: event-based communication between the document and the app [modified]memberPhil Booth2:52 18 Apr '08  
GeneralRe: event-based communication between the document and the appmemberabel_b6:11 18 Apr '08  
GeneralRe: event-based communication between the document and the appmemberPhil Booth6:44 18 Apr '08  
GeneralRe: event-based communication between the document and the appmemberPhil Booth5:11 20 Apr '08  
GeneralRe: event-based communication between the document and the appmemberabel_b5:38 4 Jun '08  
GeneralRe: event-based communication between the document and the appmemberPhil Booth23:49 4 Jun '08  
GeneralRe: event-based communication between the document and the appmemberabel_b7:13 5 Jun '08  
GeneralRe: event-based communication between the document and the appmemberabel_b11:27 27 Jun '08  
GeneralRe: event-based communication between the document and the appmemberabel_b4:42 8 Aug '08  
GeneralRe: event-based communication between the document and the appmemberabel_b5:55 22 Sep '08  
GeneralRenHost.resx is missingmemberMember 433656123:50 28 Feb '08  
GeneralRe: RenHost.resx is missingmemberPhil Booth0:01 29 Feb '08  
GeneralRe: RenHost.resx is missingmemberMember 43365610:10 29 Feb '08  
GeneralRe: RenHost.resx is missingmemberMember 43365610:41 6 Mar '08  
GeneralDid not workmembernji7811:00 9 Oct '07  
GeneralRe: Did not workmemberPhil Booth22:31 9 Oct '07  
GeneralRe: Did not workmemberflypi7:20 6 Nov '07  
GeneralRe: Did not workmemberPhil Booth5:59 13 Nov '07  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 5 Dec 2007
Editor: Smitha Vijayan
Copyright 2007 by Phil Booth
Everything else Copyright © CodeProject, 1999-2008
Web11 | Advertise on the Code Project