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

Declarative Programming--Unifying Form And Web Development

By , , 23 Nov 2004
 

Introduction

This is a concept piece that is intended to whet your appetite for declarative programming and the idea that maybe, just maybe, it is possible to unify development for System.Windows.Forms and System.Web.UI.WebControls namespaces, at least for simple applications.

Now, granted, "real" web pages have lots of JavaScript to reduce post-backs, go through a lot of optimization at the server, need to deal with real world issues like traffic, etc. And a calculator example, where each button click is a post-back, is definitely not the best example!

Click here for an online demo.

How Does It Work?

Very simple. Given a MyXaml markup file that defines the UI in the System.Windows.Forms namespace, a very simple XSLT, written by Justin, converts the markup to one that can live in the System.Web.UI.WebControls namespace. So, one markup file drives both Form and Web UI's, and the event handler code is identical as well except for one line.

The Markup

The source markup is very simple. No styles, no sub-forms, etc. Simple is better when trying to pull this off.

<?xml version="1.0" encoding="utf-8"?> 
<!-- (c) 2004 Marc Clifton All Rights Reserved -->
<wf:MyXaml
  xmlns:wf="System.Windows.Forms" 
  xmlns:def="Definitions">
  <wf:Panel Name="Calc" Location="10, 10" Size="600, 400">
    <Controls>
      <wf:TextBox def:Name="display" Location="0, 0" Size="155, 20" 
          BackColor="Black" ForeColor="Yellow" Text="0.00"/>

      <wf:Button Text="C" Location="0, 20" Size="60, 25"
                 Click="OnClear" FlatStyle="System"/>
      <wf:Button Text="CE" Location="60, 20" Size="30, 25" 
                 Click="OnClearEntry" FlatStyle="System"/>
      <wf:Button Text="=" Location="95, 20" Size="60, 25" 
                 Click="OnEqual" FlatStyle="System"/>

      <wf:Button Text="7" Location="0, 50" Size="30, 28" 
                 Click="OnDigit" FlatStyle="System"/>
      <wf:Button Text="8" Location="30, 50" Size="30, 28" 
                 Click="OnDigit" FlatStyle="System"/>
      <wf:Button Text="9" Location="60, 50" Size="30, 28"
                 Click="OnDigit" FlatStyle="System"/>
      <wf:Button Text="4" Location="0, 80" Size="30, 28" 
                 Click="OnDigit" FlatStyle="System"/>
      <wf:Button Text="5" Location="30, 80" Size="30, 28" 
                 Click="OnDigit" FlatStyle="System"/>
      <wf:Button Text="6" Location="60, 80" Size="30, 28" 
                 Click="OnDigit" FlatStyle="System"/>
      <wf:Button Text="1" Location="0, 110" Size="30, 28" 
                 Click="OnDigit" FlatStyle="System"/>
      <wf:Button Text="2" Location="30, 110" Size="30, 28" 
                 Click="OnDigit" FlatStyle="System"/>
      <wf:Button Text="3" Location="60, 110" Size="30, 28" 
                 Click="OnDigit" FlatStyle="System"/>
      <wf:Button Text="0" Location="0, 140" Size="30, 28" 
                 Click="OnDigit" FlatStyle="System"/>
      <wf:Button Text="." Location="60, 140" Size="30, 28" 
                 Click="OnDigit" FlatStyle="System"/>

      <wf:Button Text="+" Location="95, 50" Size="60, 28" 
                 Click="OnAdd" FlatStyle="System"/>
      <wf:Button Text="-" Location="95, 80" Size="60, 28" 
                 Click="OnSubtract" FlatStyle="System"/>
      <wf:Button Text="*" Location="95, 110" Size="60, 28" 
                 Click="OnMultiply" FlatStyle="System"/>
      <wf:Button Text="/" Location="95, 140" Size="60, 28" 
                 Click="OnDivide" FlatStyle="System"/>
    </Controls>
  </wf:Panel>
</wf:MyXaml>

What Gets Generated?

The XSLT translates this to:

<wf:MyXaml
  xmlns:wf="System.Web.UI.WebControls, System.Web, Version=1.0.5000.0, 
            Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
  xmlns:def="Definitions">
  <wf:Panel Name="Calc" CssStyle="position:absolute; left:10px; 
            top:10px; width:600px; height:400px;">
    <Controls>
      <wf:TextBox def:Name="display" BackColor="Black" ForeColor="Yellow" 
                  Text="0.00" CssStyle="position:absolute; left:0px; top:0px;
                  width:155px; height:20px;"></wf:TextBox>

      <wf:Button Text="C" Click="OnClear" FlatStyle="System" 
          CssStyle="position:absolute; left:0px; top:20px; width:60px; 
          height:25px;"></wf:Button>
      <wf:Button Text="CE" Click="OnClearEntry" FlatStyle="System" 
          CssStyle="position:absolute; left:60px; top:20px; width:30px; 
          height:25px;"></wf:Button>
      <wf:Button Text="=" Click="OnEqual" FlatStyle="System" 
          CssStyle="position:absolute; left:95px; top:20px; width:60px; 
          height:25px;"></wf:Button>

      <wf:Button Text="7" Click="OnDigit" FlatStyle="System" 
          CssStyle="position:absolute; left:0px; top:50px; width:30px; 
          height:28px;"></wf:Button>
      <wf:Button Text="8" Click="OnDigit" FlatStyle="System" 
          CssStyle="position:absolute; left:30px; top:50px; width:30px; 
          height:28px;"></wf:Button>
      <wf:Button Text="9" Click="OnDigit" FlatStyle="System" 
          CssStyle="position:absolute; left:60px; top:50px; width:30px; 
          height:28px;"></wf:Button>
      <wf:Button Text="4" Click="OnDigit" FlatStyle="System" 
          CssStyle="position:absolute; left:0px; top:80px; width:30px; 
          height:28px;"></wf:Button>
      <wf:Button Text="5" Click="OnDigit" FlatStyle="System" 
          CssStyle="position:absolute; left:30px; top:80px; width:30px; 
          height:28px;"></wf:Button>
      <wf:Button Text="6" Click="OnDigit" FlatStyle="System" 
          CssStyle="position:absolute; left:60px; top:80px; width:30px; 
          height:28px;"></wf:Button>
      <wf:Button Text="1" Click="OnDigit" FlatStyle="System" 
          CssStyle="position:absolute; left:0px; top:110px; width:30px; 
          height:28px;"></wf:Button>
      <wf:Button Text="2" Click="OnDigit" FlatStyle="System" 
          CssStyle="position:absolute; left:30px; top:110px; width:30px; 
          height:28px;"></wf:Button>
      <wf:Button Text="3" Click="OnDigit" FlatStyle="System" 
          CssStyle="position:absolute; left:60px; top:110px; width:30px; 
          height:28px;"></wf:Button>
      <wf:Button Text="0" Click="OnDigit" FlatStyle="System" 
          CssStyle="position:absolute; left:0px; top:140px; width:30px; 
          height:28px;"></wf:Button>
      <wf:Button Text="." Click="OnDigit" FlatStyle="System" 
          CssStyle="position:absolute; left:60px; top:140px; width:30px; 
          height:28px;"></wf:Button>

      <wf:Button Text="+" Click="OnAdd" FlatStyle="System" 
          CssStyle="position:absolute; left:95px; top:50px; width:60px; 
          height:28px;"></wf:Button>
      <wf:Button Text="-" Click="OnSubtract" FlatStyle="System" 
          CssStyle="position:absolute; left:95px; top:80px; width:60px; 
          height:28px;"></wf:Button>
      <wf:Button Text="*" Click="OnMultiply" FlatStyle="System" 
          CssStyle="position:absolute; left:95px; top:110px; width:60px; 
          height:28px;"></wf:Button>
      <wf:Button Text="/" Click="OnDivide" FlatStyle="System" 
          CssStyle="position:absolute; left:95px; top:140px; width:60px; 
          height:28px;"></wf:Button>
    </Controls>
  </wf:Panel>
</wf:MyXaml>

What Does The XSLT Look Like?

The XSLT is straightforward enough:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml"/>

  <xsl:template match="*">
    <xsl:choose>
      <xsl:when test="namespace-uri(.) = 'System.Windows.Forms'">
        <xsl:element name="{name(.)}" namespace="System.Web.UI.WebControls, 
             System.Web, Version=1.0.5000.0, Culture=neutral, 
             PublicKeyToken=b03f5f7f11d50a3a">
          <xsl:copy-of select="namespace::*[not(.='System.Windows.Forms')]"/>
          <xsl:copy-of select="@*[not(name()='Location') and not(name()='Size')]"/>
          <xsl:if test="@Location or @Size">
            <xsl:attribute name="CssStyle">
              <xsl:if test="@Location">position:absolute; left:<xsl:value-of 
              select="normalize-space(substring-before(@Location,','))"/>px; 
              top:<xsl:value-of 
              select="normalize-space(substring-after(@Location,','))"/>px;
              </xsl:if>
              <xsl:if test="@Size">width:<xsl:value-of 
              select="normalize-space(substring-before(@Size,','))"/>px; 
              height:<xsl:value-of 
              select="normalize-space(substring-after(@Size,','))"/>px;
              </xsl:if>
            </xsl:attribute>
          </xsl:if>
          <xsl:apply-templates></xsl:apply-templates>
        </xsl:element>
      </xsl:when>
      <xsl:otherwise>
        <xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
          <xsl:copy-of select="namespace::*[not(.='System.Windows.Forms')]"/>
          <xsl:copy-of select="@*[not(name()='Location') and not(name()='Size')]"/>
          <xsl:if test="@Location or @Size">
            <xsl:attribute name="CssStyle">
              <xsl:if test="@Location">position:absolute; left:<xsl:value-of 
              select="normalize-space(substring-before(@Location,','))"/>px;
              top:<xsl:value-of 
              select="normalize-space(substring-after(@Location,','))"/>px;
              </xsl:if>
              <xsl:if test="@Size">width:<xsl:value-of 
              select="normalize-space(substring-before(@Size,','))"/>px; 
              height:<xsl:value-of 
              select="normalize-space(substring-after(@Size,','))"/>px;
              </xsl:if>
            </xsl:attribute>
          </xsl:if>
        <xsl:apply-templates></xsl:apply-templates>
        </xsl:element>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

The Loaders

To make all this magic work, the markup has to be parsed, which is done by MyXaml. The parsing is done in the application startup. For the Form version, this is done when Main() is called. In the Web version, it's done in Page_Load event handler.

The Form Loader

The Form version has a very simple loader:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

using MyXaml;

namespace declarativeForm
{
  public class App
  {
    [STAThread]
    static void Main() 
    {
      new App();
    }

    public App()
    {
      Parser p=new Parser();
      SimpleCalc sc=new SimpleCalc();
      Panel panel=(Panel)p.LoadObject("calcForm.xml", "Calc", sc, null);
      Form form=new Form();
      form.Controls.Add(panel);
      Application.Run(form);
    }
  }
}

The Web Loader

The Web loader is more complicated because there is no concept of session state. Therefore, the class that manages the state of the calculator (concatenating digits, remembering the last operator, etc.) has to be preserved in the Session container. Also, for every post-back, the UI has to be regenerated.

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Text;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Xml;
using System.Xml.Xsl;

using MyXaml;

namespace declarativeWeb
{
  public class WebForm1 : System.Web.UI.Page
  {
    protected System.Web.UI.WebControls.Panel formPanel;

    private void Page_Load(object sender, System.EventArgs e)
    {
      if (!IsPostBack)
      {
        SimpleCalc sc=new SimpleCalc();
        XmlDocument doc=LoadDocument();

        if (doc != null)
        {
          Parser parser=new Parser();
          Panel panel=(Panel)parser.LoadObject(doc, "Calc", sc, null);
          if (panel != null)
          {
            formPanel.Controls.Add(panel);
          }
        }

        Session["SimpleCalc"]=sc;
      }
      else
      {
        SimpleCalc sc=(SimpleCalc)Session["SimpleCalc"];
        XmlDocument doc=LoadDocument();

        if (doc != null)
        {
          Parser parser=new Parser();
          Panel panel=(Panel)parser.LoadObject(doc, "Calc", sc, null);
          if (panel != null)
          {
            formPanel.Controls.Add(panel);
          }
        }
      }
    }

    override protected void OnInit(EventArgs e)
    {
      InitializeComponent();
      base.OnInit(e);
    }

    private void InitializeComponent()
    { 
      this.Load += new System.EventHandler(this.Page_Load);
    }

    private XmlDocument LoadDocument()
    {
      XmlDocument doc=null;
      string path=MapPath("");

      try
      {
        doc=new XmlDataDocument();
        doc.PreserveWhitespace=true;
        doc.Load(path+"\\calcForm.xml");
        XslTransform xt=new XslTransform();
        xt.Load(path+"\\form2web.xslt");
        StringBuilder sb=new StringBuilder();
        StringWriter sw=new StringWriter(sb);
        xt.Transform(doc, null, new XmlTextWriter(sw), new XmlUrlResolver());

        doc=new XmlDocument();
        doc.LoadXml(sb.ToString());
        System.Diagnostics.Trace.WriteLine(sb.ToString());

      }
      catch(Exception ex)
      {
        Trace.Warn(ex.Message);
      }
      return doc;
    }
  }
}

The Calculator Event Handler Code

The calculator event handler code is identical for both Form and Web versions, except in the Form version you have to specify:

using System.Windows.Forms;

whereas in the Web version, you specify:

using System.Web.UI.WebControls;

Here is the Web version:

using System;
using System.Globalization;
using System.Web.UI.WebControls;    // Form version is System.Windows.Forms

using MyXaml;

namespace declarativeWeb
{
  public class SimpleCalc
  {
    private bool cleared;
    private string lastOp;
    private string lastValue;
    private NumberFormatInfo formatProvider;

    [MyXamlAutoInitialize] private TextBox display=null;

    public SimpleCalc()
    {
      cleared=true;
      lastOp=String.Empty;
      lastValue=String.Empty;

      formatProvider=new NumberFormatInfo();
      formatProvider.NumberDecimalDigits=2;
    }

    public void OnClear(object sender, EventArgs e)
    {
      display.Text="0.00";
      cleared=true;
      lastOp=String.Empty;
      lastValue=String.Empty;
    }

    public void OnClearEntry(object sender, EventArgs e)
    {
      display.Text="0.00";
      cleared=true;
    }

    public void OnDigit(object sender, EventArgs e)
    {
      Button btn=(Button)sender;
      if (cleared)
      {
        display.Text=btn.Text;
        cleared=false;
      }
      else
      {
        display.Text=display.Text+btn.Text;
      }
    }

    public string ProcessLastOp(string val)
    {
      double d=0;
      switch(lastOp)
      {
        case "+":
        {
          d=Convert.ToDouble(lastValue) + Convert.ToDouble(val);
          break;
        }
        case "-":
        {
          d=Convert.ToDouble(lastValue) - Convert.ToDouble(val);
          break;
        }
        case "*":
        {
          d=Convert.ToDouble(lastValue) * Convert.ToDouble(val);
          break;
        }
        case "/":
        {
          if (Convert.ToDouble(val) != 0.0)
          {
            d=Convert.ToDouble(lastValue) / Convert.ToDouble(val);
          }
          break;
        }
      }
      lastValue=d.ToString("N", formatProvider);
      return lastValue;
    }

    public void OnAdd(object sender, EventArgs e)
    {
      if (lastValue==String.Empty)
      {
        lastValue=display.Text;
      }
      else
      {
        lastValue=ProcessLastOp(display.Text);
        display.Text=lastValue;
      }
      lastOp="+";
      cleared=true;
    }

    public void OnSubtract(object sender, EventArgs e)
    {
      if (lastValue==String.Empty)
      {
        lastValue=display.Text;
      }
      else
      {
        lastValue=ProcessLastOp(display.Text);
        display.Text=lastValue;
      }
      lastOp="-";
      cleared=true;
    }

    public void OnMultiply(object sender, EventArgs e)
    {
      if (lastValue==String.Empty)
      {
        lastValue=display.Text;
      }
      else
      {
        lastValue=ProcessLastOp(display.Text);
        display.Text=lastValue;
      }
      lastOp="*";
      cleared=true;
    }

    public void OnDivide(object sender, EventArgs e)
    {
      if (lastValue==String.Empty)
      {
        lastValue=display.Text;
      }
      else
      {
        lastValue=ProcessLastOp(display.Text);
        display.Text=lastValue;
      }
      lastOp="/";
      cleared=true;
    }

    public void OnEqual(object sender, EventArgs e)
    {
      if (lastValue != String.Empty)
      {
        display.Text=ProcessLastOp(display.Text);
        lastValue=String.Empty;
        lastOp=String.Empty;
        cleared=true;
      }
    }
  }
}

Where's The Smoke And Mirrors?

There's only one "trick" being employed here. Absolute positioning is used and Web controls don't support that except by using the style attribute in the HTML. .NET's support for this is via the Style property. However, this property does not accept a string that would be used to construct the HTML style attribute. Instead, the WebControl.Style property is CssStyleCollection type. To make matters worse, although this type behaves sort of like a dictionary (it has a key-value pair Add method), it isn't derived from IDictionary.

Therefore, the smoke and mirrors is that MyXaml has custom property setter code for the CssStyle attribute. When it encounters the CssStyle attribute, it invokes a handler for this attribute (CssStyleCustomProperty) that decodes the string and loads up the CssStyleCollection for the Style property of the instance being parsed. At least the mechanism that is used is a general purpose custom attribute handler, rather than embedding web style processing inside the MyXaml parser directly.

The Downloads

For the web demo:

  1. Create an ASP.NET web application project.
  2. Copy the the files in the web download into the folder for your project, overwriting the WebForm.* files.
  3. Add a reference to the MyXaml.dll assembly that got put into your bin directory.

For the form demo, just unzip the download and compile the provided csproj.

A Note To MyXaml Users

If you want to compile against the MyXaml source code, there's a minor change made to MyXaml to deal with the prefix on the MyXaml node. In InitializeNamespaces, change:

XmlNode uiNode=doc.GetElementsByTagName("MyXaml")[0];

to

XmlNode uiNode=doc.DocumentElement;

Because MyXaml is a GPL open source project, I would prefer that people obtain the source code directly from the MyXaml website and acknowledge that they agree to the licensing terms. The downloads include only the MyXaml assembly.

GAC Issues

MyXaml registers itself into the GAC, and for some very annoying reason, I had problems with the web version acquiring the correct MyXaml file. If you suspect such a problem, remove MyXaml from the GAC (note that the MyXaml project has a post-build step that registers itself into the GAC, so you might want to remove that too).

Conclusion

Within the confines of simple UI controls, simple requirements, and where post-back performance isn't an issue, declarative programming and XSLT makes it possible to create both form and web applets from the same code base.

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 Authors

Marc Clifton
United States United States
Member
Marc is the creator of two open source projets, MyXaml, a declarative (XML) instantiation engine and the Advanced Unit Testing framework, and Interacx, a commercial n-tier RAD application suite.  Visit his website, www.marcclifton.com, where you will find many of his articles and his blog.
 
Marc lives in Philmont, NY.

J. Dunlap
Web Developer
United States United States
Member
My main goal as a developer is to improve the way software is designed, and how it interacts with the user. I like designing software best, but I also like coding and documentation. I especially like to work with user interfaces and graphics.
 
I have extensive knowledge of the .NET Framework, and like to delve into its internals. I specialize in working with VG.net and MyXaml. I also like to work with ASP.NET, AJAX, and DHTML.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralAlso look at HabaneromemberErichero30 Oct '08 - 1:06 
This is definitely the way we should be going, extracting common UI design concepts into a generic format, and XAML helps along that path.
 
Having developed Habanero with a similar purpose, we integrated Visual WebGui, which creates an AJAX-based framework that emulates WinForms on the web. Having an API similar to WinForms, we were able to integrate Visual WebGui into the runtime-generated presentation layer of Habanero, and thus launch an application either on desktop or web.
 
We have a CodeProject article on this: http://www.codeproject.com/KB/dotnet/desktopandweb.aspx[^]
 
Now that we're looking to add better skinning options, we'll take a much closer look at XAML and refer back to this example as a reference point. Thanks.
GeneralIdea - Intermediate Abstract Syntax TreememberPhilip Laureano31 Dec '06 - 12:58 
Marc,
 
From what I can gather of this article, it looks like you're using the XSLT to transform the System.Windows.Forms classes into their System.Web.* equivalents--so in short, what you're basically doing is deciding which family of classes to instantiate at runtime.
 
Now, if you parse MyXaml into an intermediate AST with tree nodes containing the exact types that you want to instantiate (whether it System.Web.* or System.Windows.Forms.*), I bet you could pull off unifying both web and winforms by iterating through that AST and swapping one family of types for another, at least in theory...
 
Thoughts?

GeneralRe: Idea - Intermediate Abstract Syntax TreeprotectorMarc Clifton31 Dec '06 - 13:12 
Philip Laureano wrote:
Thoughts?

 
It looks like you're catching up on your reading during the holiday break. Smile | :)
 
But yes, this is something I've been planning to add to MyXaml--the ability to essentially redirect a tag or property to a different value. I had thought to do the replacing while parsing the xml. I'll have to read up on AST's.
 
Besides doing this with SWF / web, you could also use the same approach to possibly swap out completely different libraries or replace legacy classes with new ones. Lots of possibilities.
 
Marc
 

Thyme In The Country

People are just notoriously impossible. --DavidCrow
There's NO excuse for not commenting your code. -- John Simmons / outlaw programmer
People who say that they will refactor their code later to make it "good" don't understand refactoring, nor the art and craft of programming. -- Josh Smith


GeneralRe: Idea - Intermediate Abstract Syntax TreememberPhilip Laureano1 Jan '07 - 12:00 
Hi Marc,
 
I'm currently working on my own version of a XAML parser that's very similar to yours. The only difference is that unlike MyXaml, my library compiles directly to IL through the use of .NET 2.0's Lightweight Code Generation (LCG).
 
Other then that, I'm using a universal event handler so I can tie delegates of any signature to a generic event handler. For me, I wanted a little more flexibility than using EventHandler-typed delegates all over the place, and dynamically generating the delegates to match any event signature.
 
At this point, I'm not sure whether I'll still need an event pool. It seems a little redundant with the universal event handler...
 
Anyway, do you mind if we compare notes? Smile | :)
 

GeneralRe: Idea - Intermediate Abstract Syntax TreeprotectorMarc Clifton1 Jan '07 - 12:02 
Philip Laureano wrote:
Anyway, do you mind if we compare notes?

 
I'd love to. Sounds like some great work you're doing.
 
Marc
 

Thyme In The Country

People are just notoriously impossible. --DavidCrow
There's NO excuse for not commenting your code. -- John Simmons / outlaw programmer
People who say that they will refactor their code later to make it "good" don't understand refactoring, nor the art and craft of programming. -- Josh Smith


GeneralmyAXmlmemberjsanjosemgmail.com8 Dec '05 - 6:35 
Maybe this is a stupid question, but: may I use this aproach to show a .myxaml file on a web page? I have playing with clock.myaxml that I downloaded from your article http://www.codeproject.com/dotnet/vgclock.asp.
 
Thanks.
GeneralA Declarative Tour-De-FordememberKim Alexander18 Apr '05 - 23:47 
Marc/Justin,
 
Let me say first of all that I have encounterd your works off and on in my xml, xslt, dynamic ui work for quite some time now. I've been very interested in SVG and it's promise, but with MS inventing XAML and it being in LOOOOOONG-AWAY-horn I wasn't too interested although the technologies seemed similar.
 
As I was catching up on my on this insomiatic night of short sleep induced by creative vigor. I started reading some blogs, just to catch up. Taking care of the familiar's I reached the obscure blogs I'd not accessed in quite some time. It was then while reading Frank Hilemans's blog that I found this link to your article. http://weblogs.asp.net/frank_hileman/archive/2004/11/24/269227.aspx
 
After reading your article I was blown-away, and inquired to myself when it was written. Fully expecting a date within the last two weeks or so. But no. However the content and subject is very current and I congratulate you on once again providing thought-provoking, imagination capturing solutions to problems I (for one developer) long for solution to.
 
BTW: I'm interested in using SVG to bridge from VISIO Client app to Browser. What do I mean by that? I'd like to provide an interface in a browser similar to Visio. Possible? I don't know. But my needs are only a subset of what Visio is capable of.
 
Oh boy! Now I'm really awake!
 
Thanks Marc and Justing
 
Kim Alexander
OLAP, Web, XML Developer
GeneralCool!memberbeardman24 Nov '04 - 5:27 
Looks like a great idea! Its something my job's going to involve me doing soon...
How well does this support custom controls?
GeneralRe: Cool!protectorMarc Clifton24 Nov '04 - 5:37 
beardman wrote:
How well does this support custom controls?
 
Well, I'm not sure what degree of complexity of custom control you are meaning. For this to work you have to use controls that map relatively easily between form and web. The System.Web.UI namespace has a UserControl class, so you can create user controls from the other components.
 
Marc
 
MyXaml
Advanced Unit Testing

GeneralConcept clearstaffPaul Watson23 Nov '04 - 23:17 
I think this is a very interesting concept piece and you made it very clear that it was exactly that. Good article.
 
regards,
Paul Watson
South Africa
 
Michael Dunn wrote:
"except the sod who voted this a 1, NO SOUP FOR YOU"
 
Crikey! ain't life grand?

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 23 Nov 2004
Article Copyright 2004 by Marc Clifton, J. Dunlap
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid