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

MyXAML--XAML-style gui generator (added styles)

By , 9 Mar 2004
 

Latest News:

The name is now official:  MyXaml!!!

MyXaml now supports Styles!  (see revision history).

Interested in participating in the development of this technology?  Join the open-source project!  This project is NOT intended to emulate Longhorn's markup language nor the MSAvalon namespace.  Rather, MyXAML supports namespaces without using a DOM backbone, instead using the property setters defined in the namespace classes directly.

Contents

If you rate this article, please explain your rating!

Revision History

3/10/04

  • Style sheets
  • Revamped markup syntax -- removed need for the FormBase attribute
  • Now can instantiate any class in a declared namespace at the root level, rather than just a System.Windows.Forms class.

An example of a style specification is:

<xgg:Style def:Name='XP'>
  <xgg:StyleProperties>
    <xgg:PropertyStyle FlatStyle='System'/>
  </xgg:StyleProperties>
</xgg:Style>

<xgg:Style def:Name='ButtonStyle' BasedOn='{XP}'>
  <xgg:StyleProperties>
    <xgg:PropertyStyle Size='80, 25'/>
  </xgg:StyleProperties>
</xgg:Style>

And the usage is straight forward:

<Button def:Name='OKButton'
        Style='{ButtonStyle}'
        Location='225, 10'
        Visible='true'
        Click='OnOK'
        Text='&amp;OK'/>

A couple notes about Style:  Derived styles supersede properties defined in the "BasedOn" style.  Because attributes are parsed from left to right, an object with a Style attribute can override a the property value by specifying the property value to the right of the Style attribute.

Refactoring Your Previous Markup

To review the changes made to the markup itself, see the body of this article.  Basically, the old form was:

<Canvas Name="Foo" FormBase="Form"..></Canvas>

The new markup structure is:

<Form Name="Foo"...></Form>

More information can be found on the http://www.myxaml.com/ website--click on Tutorials.

2/25/04 - Many new features

  • support for menus
  • support for class namespaces via xml namespaces
  • support for DataSource properties used in list controls as an attribute
  • support for DataSource element for Xml defined lists
  • support for DataBinding
  • inline code support
  • code-behind support
  • improved property setters
  • revamped XML syntax to be more like XAML
  • constructor parameters when instantiating runtime classes
  • and many more features

2/16/04 - Added support for properties defined as attributes and for form events

2/13/04 - Initial Release

As per Leppie's suggestion, I have modified the form generator to handle XML attributes as a means of specifying property values.  The property model architecture is still required for more complicated property types however.

This admittedly makes the XML considerably more readable!  Currently, both modalities are supported (using attributes vs. using nodes), so you can mix and match as you please, but that may change in the future.

Introduction

This is a complete rewrite of the article.  Rather than going into code examples, I'm going to illustrate each of the features of this library.

The XML

First off, let's start with the fun part, which is specifying the form in XML.  I'll use the above screenshot to demonstrate the various features of the generator.  After this section, I'll have some architectural diagrams that illustrate different use models.

General Architecture

An important consideration is that the nodes in the XML map directly to properties of the current context instance.  For example, when a form is instantiated with a form base of "Form", the context instance is a System.Windows.Forms.Form, and you may set attributes to any of the properties that the Form class provides, including property collections such as Menu and Controls, as long as they are supported either with by a TypeConverter or a property setter model.  The only exception to this hardfast rule is a DataSource element, in which the child nodes, Item, do not correlate to anything in particular because the DataSource property takes an Object type.

Another important consideration is that, rather than inlining a control's attributes and children, you can at any point specify Canvas as an attribute, and define a new type for that specific control.  We'll see example of this later.  What that means is that, for the specific control, you may define code-behind instances, as all root nodes allow for code-behind instances.

Third Party Components, Namespaces, and the XML Header

To begin with, let's inspect the XML header:

<?xml version="1.0" encoding="utf-8"?>

<UI xmlns="System.Windows.Forms, System.Windows.Forms, Version=1.0.5000.0, 
Culture=neutral, PublicKeyToken=b77a5c561934e089"

xmlns:ka="OutlookBar, OutlookBarAssembly, Version=1.0.1.2, Culture=neutral, 
PublicKeyToken=null"

xmlns:def="Definition">

<Form Name='PropertyTest' Location='10, 10' Size='600, 330' 
      Visible='false' BackColor='LightSteelBlue' Closing='OnCloseEvent'
      Load='PropertyTestLoaded' 
Text='Simple Test Form'>
Notice the use of namespaces to provide fully qualified names for the assemblies.  This allows you to utilize third party components in your XML definition.  Rather than using Microsoft's XAML namespace, I am choosing to code the assembly information directly in the namespace.  This information has to reside somewhere, and this isn't XAML.

Defining A Form, Properties and Events

In XAML, the root node is typically a form in which you specify the coordinates of the child objects, so I chose to use the same name.  The form is specified as:

<Form Name='PropertyTest' Location='10, 10' Size='600, 330' 
Visible='false' BackColor='LightSteelBlue' Closing='OnCloseEvent' Load='OnLoad' 
Text='Simple Test Form'>
Here, various properties are being set, and the "Load" event is being wired to an event handler.  The event handler is a method name that is available in the target instance provided to the XmlGuiGenerator.  For example:
public class Demo
{
  Form form;
  public Demo()
  {
    form=(Form)Generator.LoadForm("propertyTest.xml", "PropertyTest", 
          this, null);
    form.ShowDialog();
  }

  public void OnLoad(object sender, EventArgs e)
  {
    MessageBox.Show("OnLoad", sender.ToString());
  }
}

Similar to the System.Web.UI namespace, the XmlGuiGenerator will fire the "Load" event for any control that is instantiated, if the event is defined.

Notice that the FormBase is 'Form'.  The form base can be anything, really, and we'll discuss that later on.  A root node is special in that it can also have a code-behind or inline code instance that is compiled and instantiated at runtime.  Several examples of this will be discussed later.

Defining A Menu Structure

If the root node or child control supports the Menu property, you may define a menu:

<Menu>
  <MenuItems>
    <MenuItem Text='&amp;File' Popup='OnPopup'>
    <MenuItems>
      <MenuItem Text='New'/>
      <MenuItem Text='-'/>
      <MenuItem Text='E&amp;xit' Click='ExitApp'/>
    </MenuItems>
  </MenuItem>
  <MenuItem Text='&amp;Edit'/>
  <MenuItem Text='&amp;View'/>
  </MenuItems>
</Menu>

Controls

Controls are added to the Controls collection, for example:
<Controls>
  <Button Location='225, 100' Size='80, 25' Visible='true'
          BackColor='Control'
          Click='OnMyEvent'>Click Event!</Button>
  <Label Location='225, 50' Size='120, 40' Visible='true'
         Font='French Script MT, 22pt, style=Bold'>Font Test!</Label>
  <Label Location='10, 12' Size='50, 15' Visible='true'>Edit 1:</Label>
  <Label Location='10, 37' Size='50, 15' Visible='true'>Edit 2:</Label>
  <TextBox Location='60, 10' Size='100, 20' Visible='true'/>
  <TextBox Location='60, 35' Size='100, 20' Visible='true' Enabled='false'>
           Disabled</TextBox>
  <Panel BorderStyle='Fixed3D' Top='95' Left='20' Size='200, 178'
         Visible='true' BackgroundImage='jojo.jpg' Anchor='Bottom, Left'/>
  <GroupBox Location='225, 130' Size='120, 60' Visible='true'
            Text='First Group Box' Font='MS Sans Serif, 8pt, style=Bold'>
    <Controls>
      <RadioButton Location='10, 15' Size='70, 15' Visible='true'
            Font='MS Sans Serif, 8pt' Load='InitialRadioButtonState'>
            Like</RadioButton>
      <RadioButton Location='10, 30' Size='70, 15' Visible='true'
            Font='MS Sans Serif, 8pt'>Don't Like</RadioButton>
    </Controls>
  </GroupBox>
  ...

This is a good example of inlined controls, in which the group box specifies child controls that it contains.

Canvased Controls

The second group box in the demo is canvased, meaning that it is defined in a separate root node.  In the parent form XML, it declared as:

<GroupBox Canvas="GroupBox2"/>

A separate canvas defines the group box attributes and collections:

<GroupBox Name='GroupBox2' Location='225, 200' Size='120, 60' Visible='true'
          Text='Second Group Box' Font='MS Sans Serif, 8pt, style=Bold'>
  <Controls>
    <RadioButton Location='10, 15' Size='70, 15' Visible='true'
        Font='MS Sans Serif, 8pt' Load='InitialRadioButtonState'>
        To Click</RadioButton>
    <RadioButton Location='10, 30' Size='100, 15' Visible='true'
        Font='MS Sans Serif, 8pt'>Or Not To Click</RadioButton>
  </Controls>
</GroupBox>

Note that the events are handled by the target context declared by the parent form, which in this case is the class instance passed in to the generator as described above.  (More on event context later).

Tab Control

Similarly, tab pages can be inlined or canvased:

<TabControl Location='350, 10' Size='240, 250' Visible='true'>
  <TabPages Canvas='TabPage1'/>
  <TabPages Canvas='TabPage2'/>
  <TabPages Name='TabPage3' Text='ListView' Load='PopulateListView'>
    <Controls>
      <ListView Location='5, 10' Size='222, 210' HeaderStyle='Nonclickable'
        FullRowSelect='true' GridLines='true' View='Details'>
        <Columns Width='150' TextAlign='Left'>State</Columns>
        <Columns Width='50' TextAlign='Center'>Abbr.</Columns>
      </ListView> 
     </Controls>
  </TabPages>
  <TabPages Canvas='TabPage4'/>
</TabControl>

(In fact, the generator will allow you to specify a canvas as well as inlined collections, but that feature should not be relied upon).

Third Party Controls

Remember the namespace "ka" in the XML header.  He's how my Outlook Bar control is implemented in the XML:

<TabPage Name='TabPage1' Text='Custom Control'>
...
  <Controls>
    <ka:OutlookBar Location='10, 10' Size='150, 210' Visible='true'
        BorderStyle='FixedSingle' Load='MyForm.OnLoad'/>
  </Controls>
</TabPage>

Note that the OutlookBar is declared with the namespace "ka" prefix.  This tells the generator that the class name for this control is coming from the namespace declared in the XML header.  Using the namespace, the fully qualified name can be obtained, and the class instantiated.

Now, what you ask, is in-between that "...", and what's "MyForm.OnLoad"???  Well, read-on.

Inline Code

The tab pages illustrate different means of implementing code-behind.  The first is inlining.  The full canvas for TabPage1 is defined as:

<TabPage Name='TabPage1' Text='Custom Control'>
  <def:Code language="'C#'">
    <reference assembly="System.Drawing.dll"/>
    <reference assembly="System.Windows.Forms.dll"/>
    <reference assembly="OutlookBarAssembly.dll"/>
    <![CDATA[
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;

using OutlookBar;

class MyForm
{
  private OutlookBar.OutlookBar outlookBar;

  // controls in the tab page do not exist yet when the code-behind is 
  // instantiated!
  public MyForm() {}

  public void OnLoad(object sender, EventArgs e)
  {
    outlookBar=(OutlookBar.OutlookBar)sender;
    IconPanel iconPanel1=new IconPanel();
    IconPanel iconPanel2=new IconPanel();
    IconPanel iconPanel3=new IconPanel();
    outlookBar.AddBand("Outlook Shortcuts", iconPanel1);
    outlookBar.AddBand("My Shortcuts", iconPanel2);
    outlookBar.AddBand("Other Shortcuts", iconPanel3);

    iconPanel1.AddIcon("Outlook Today", Image.FromFile("img1.ico"),
       new EventHandler(PanelEvent));
    iconPanel1.AddIcon("Calendar", Image.FromFile("img2.ico"),
       new EventHandler(PanelEvent));
    iconPanel1.AddIcon("Contacts", Image.FromFile("img3.ico"),
       new EventHandler(PanelEvent));
    iconPanel1.AddIcon("Tasks", Image.FromFile("img4.ico"),
       new EventHandler(PanelEvent));
    outlookBar.SelectBand(0);
  }

  public void PanelEvent(object sender, EventArgs e)
  {
    Control ctrl=(Control)sender;
    PanelIcon panelIcon=ctrl.Tag as PanelIcon;
    MessageBox.Show("#"+panelIcon.Index.ToString(), "Panel Event");
  }
}
]]>
    </def:Code>
    <Controls>
    <ka:OutlookBar Location='10, 10' Size='150, 210' Visible='true'
        BorderStyle='FixedSingle' Load='MyForm.OnLoad'/>
  </Controls>
</TabPage>

Defining References

Any inline and code-behind code must declare the assemblies that it is referencing for the JIT compiler to correctly generate the assembly.

Wiring Events To Event Handlers

The generator allows you to define as many classes as you like in the code-behind.  It manages the instance of each class, and since there can only be one instance per class (at least that it knows of), you can specify the instance that will handle events by prefixing the class name to the method name, in the format <className>.<methodName>, as illustrated above in "Load='MyForm.OnLoad'.

If you leave off the class name, the event will instead be wired to the event context passed in to the generator when the form is created.

Notice that the source language is also defined in the XML, allowing you to mix different languages for your code-behind source!

Code-Behind Code

If you would rather work with a .cs or .vb file and take advantage of syntax checking and automated help, you can specify the code behind as residing in a file rather than inline.  This is demonstrated in the second tab page:

<TabPage Name='TabPage2' FormBase='TabPage' Text='ListBox'>
  <def:CodeBehind Src="InitDataSource.cs">
  <reference assembly="System.Windows.Forms.dll"/>
  </def:CodeBehind>
  <Controls>
    <ListBox Name='States' Location='10, 10' Size='130, 210'
       DataSource='ListBoxDS.DataSource' DisplayMember='LongName'
       ValueMember='ShortName'
       SelectedValueChanged='ListBoxDS.ShowValue'/>
    <Label Location='150, 10' Size='60, 15' Visible='true'>By event:</Label>
    <TextBox Name='ByEvent' Location='150, 25' Size='75, 20' Visible='true'
       ReadOnly='true'/>
    <Label Location='150, 55' Size='60, 15' Visible='true'>
           By binding:</Label>
    <TextBox Location='150, 70' Size='75, 20' Visible='true' ReadOnly='true'>
      <DataBindings>Text, ListBoxDS.DataSource, ShortName</DataBindings>
    </TextBox> 
  </Controls>
</TabPage>

This also illustrates DataBinding.  Read on.

DataBinding

Controls that support the DataBinding property can have the property set in the XML.  The format is simple:

<DataBindings>Text, ListBoxDS.DataSource, ShortName</DataBindings>

You specify the field to bind to, the data source, and the property name in data source that will return the data.  Note that the data source must be obtained from a property from a context instance--either the code-behind or the instance supplied to the generator.  Inspecting the C# code that comprises the code behind, the ListBoxDS class is automatically instantiated by the generator (as is, interestingly enough, a single instance of the DataItem class--in future release, I'll implement a class attribute that tells the generator to exclude instantiating the class):

public class ListBoxDS
{
  // the DataSource property can handle any IList derived object
  private ArrayList dataSource;

  // must be a property! (not a field!!!)
  public ArrayList DataSource
  {
    get {return dataSource;}
  }

  public ListBoxDS()
  {
    dataSource=new ArrayList();
    dataSource.Add(new DataItem("AL", "Alabama"));
    dataSource.Add(new DataItem("WA", "Washington"));
    dataSource.Add(new DataItem("WV", "West Virginia"));
    dataSource.Add(new DataItem("CT", "Connecticut"));
    dataSource.Add(new DataItem("CA", "California"));
    dataSource.Add(new DataItem("RI", "Rhode Island"));
    dataSource.Add(new DataItem("NY", "New York"));
  }

  public void ShowValue(object sender, EventArgs e)
  {
    ListBox lb=(ListBox)sender;
    TabPage tp=(TabPage)lb.Parent;
    TextBox tb=(TextBox)FormHelper.FindControl(tp, "ByEvent");
    tb.Text=lb.SelectedValue.ToString();
  }
}

The DataItem class is defined as:

public class DataItem
{
  private string shortName;
  private string longName;

  public DataItem(string shortName, string longName)
  {
    this.shortName=shortName;
    this.longName=longName;
  }

  public string ShortName
  {
    get {return shortName;}
  }

  public string LongName
  {
    get {return longName;}
  }

  public override string ToString()
  {
    return LongName+" ("+ShortName+")";
  }
}

Inline DataSource

Alternatively, you may have a short list that you simply wish to hardcode members for, rather than creating programmatically.  This is accomplished by specifying the DataSource as an element in the XML rather than an attribute, as is illustrated in the fourth tab page:

<MyCodeBehindClass Name='TabPage4' Text='Inherit'
     Load='MyCodeBehindClass.OnLoad'>
  <def:CodeBehind Src="MyCodeBehind.cs">
  <reference assembly="System.Windows.Forms.dll"/>
  </def:CodeBehind>
  <Controls>
    <Label Location='10, 10' Size='150, 15' Visible='true'>Test</Label>
    <Label Location='10, 42' Size='50, 15' Visible='true'>Colors</Label>
    <ComboBox Name='Colors' Location='60, 40' Size='100, 100'
      DisplayMember='text' ValueMember='value'>
      <DataSource>
        <item value='1' text='Red'/>
        <item value='2' text='Green'/>
        <item value='3' text='Blue'/>
      </DataSource>
    </ComboBox>
  </Controls>
</MyCodeBehindClass>

Note that the items must be specified to have "value" and "text" properties.

Architecture And Usage

The XmlGuiGenerator is a very flexible thing (in fact, not limited to forms/controls at all!), and I thought I'd put together some usage scenarios diagrams.  Hopefully they'll give you a flavor for the richness of this tool.

A Simple Example

In this scenario, there is no code behind and the XML doesn't specify any events itself.  Here, the application must wire up any event handlers programmatically, just as is done in regular development.

Auto Event Wiring

In this example, the generator manages the wiring of events automatically.  The event is specified in the XML along with the method name in a class instance specified by the application.  Of course, nothing prevents the application from programmatically wiring up other events.

Code Behind Event Handlers

In this example, the application does not provide an event context.  It must wire up events programmatically.  Also, since there is code-behind defined in the XML, the events can be handled by the code-behind instead of the application.

Code Behind And Application Context Events

In this example, both the application and the code-behind event handlers are wired by events specified in the XML, and both participate in handling the events.

Child Controls

This is an example of how child controls (or collections in general) are instantiated, and how events can be handled by both the application and code-behind context for both the main form and the child controls.  This diagram assumes that all children are specified inline.

Multiple Canvases

This example is a bit more complicated.  Here, we have child controls that are specified with separate canvases, allowing the child to have unique code-behind for managing events.

Inheriting From Code-Behind

Finally, instead of specifying the form base as a class in the System.Windows.Forms namespace (or other namespace), you can specify the form base to be of the class defined in the code-behind.  As long as the code-behind class is derived from the appropriate class, you can set properties and events in both the code-behind and the super-class.

Debugging

Debugging XML generated GUI's is not easy.  There are a couple projects in the works to make your life easier.  One is a Form2Xml converter, that parses an existing Visual Studio Designer developed form.  Another is a generic form layout tool (http://www.divil.co.uk/net/articles/designers/hosting.asp).  Anyone willing to work on those or if you have better ideas, please contact me.

Credits

Credits go to CPian Leppie for his many suggestions, CPian tditiecher for finding a bug, Kent Roylance for his patience in working with the CVS repository of this effort (contact me if you are interested in contributing, BTW), creating a Form2Xml utility and pointing me to a generic form designer, jconwell for his excellent article on Dot Net Script, and Roy Davis for his many excellent suggestions.

Other Links

It has been pointed out that this is a lot like XAML that is planned in the release of Longhorn.  The funny thing is, I didn't even now about XAML when I started this project.  Oh well.  Ignorance is bliss.  For further reading on the XAML reference:  http://longhorn.msdn.microsoft.com/lhsdk/port_ref_elements.aspx.

Licensing

Use of this GUI generator must comply with the terms of the GNU General Public License.

Conclusion

Consider that this kind of a generator is not just restricted to windows form controls.  It can be easily applied to web form controls, and in fact generalized to construct and initialize any kind of object!  Using reflection, it would be possible to provide setters and getters of control values into specific class instance members as well.  There's a lot you can do with this.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Marc Clifton

United States United States
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.

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   
GeneralDead ProjectmemberTakuan.Daikon14-Aug-09 7:33 
I hate it when I find something that looks very much like what I had been searching for, only to find that the project is dead, the website is down, and yet Google and 100 other sites are still pointing to it.
 
It's a major letdown, especially when the article says "Download the latest from [dead website here]" Mad | :mad:
GeneralRe: Dead ProjectprotectorMarc Clifton14-Aug-09 10:40 
It's not dead. There's many articles I've written here on CP, and the code is basically as developed as one can take it.
 
As for the website being down, your timing is bad...the hard disk on my server crashed yesterday and I'm working with the provider on resurrecting the server. It'll probably be a while though.
 
Marc
 
Will work for food.
Interacx


I'm not overthinking the problem, I just felt like I needed a small, unimportant, uninteresting rant! - Martin Hart Turner


GeneralRe: Dead ProjectmemberTakuan.Daikon14-Aug-09 12:18 
Ah, I'm very glad to hear that it's not dead, because it looks like just the thing I was looking for Smile | :)
 
Thanks for the reply, very much appreciated!
GeneralRe: Dead Projectmembertorokze0132-Oct-09 21:00 
Marc,
 
Could you tell something about when your site will be accessible again?
 
Zolee
GeneralRe: Dead ProjectprotectorMarc Clifton3-Oct-09 2:58 
torokze013 wrote:
Could you tell something about when your site will be accessible again?

 
I'm working ever so slowly on it. Given my rate of work, it'll be another month or so.
 
Marc
 
Will work for food.
Interacx


I'm not overthinking the problem, I just felt like I needed a small, unimportant, uninteresting rant! - Martin Hart Turner


GeneralRe: Dead Projectmembertorokze0134-Oct-09 2:30 
Any temporary download site until yours become alive?
 
Zolee
GeneralRe: Dead Projectmembermpemberton27-Dec-09 16:06 
Definitely missing you Marc. Would love to see this code as well as all your other fantastic code (and maybe what you are working on now). Smile | :)
GeneralRe: Dead ProjectmemberMember 459697810-Mar-10 6:11 
Still working on the reconstruction of your website, or
will MyXaml never be available again?
QuestionWPF?memberdevvvy1-Jan-09 16:36 
hello
 
Sorry new to both MyXAML and WPF - is this going to be compatibile with WPF in future? That we can define declaratively define user interface layout and elements through MyXAML config then MyXAML will, during runtime, generate user interface for Winform (today 2.0)/ASP.NET (today 2.0)/WPF (in future?)
 
That there'll be no need to rewrite code if porting an app from say Winform to ASP.NET? Is that the idea?
 
Thanks!
 
dev

QuestionXaml and C# question - can anyone help me?memberMichael_AK6-Jun-08 22:03 
I'm new to the .NET Framework and programming at a new job using Visual Studio 2008.
I'm using Xaml for the user interface and C# to add functionality to Xaml.
 
Question: I need the coding for both Xaml and C# regarding a Menu Item at the top of a window.
The menu item is called 'File'. In Xaml, when 'File' is pressed, a menu drop down shows including
'New...' as one of the choices. I need coding example for both Xaml and C# where if I click on the
'New...' in the drop-down, that another window will open up. I hear that you need an event handler of some sort to do this. I'm very new to this. I see event handler stuff for a 'button' in a window but
not for a menu item chosen. Please help!
 
Thanks
Michael_M
QuestionDesigner Support?mvpPhilip Laureano11-Mar-08 13:57 
Hi Marc,
 
Aside from using Form2Xml, did anyone manage to come up with a designer host for MyXaml yet? I've managed to write my own version of you MyXaml engine, and I just might want to take a crack at it with LinFu...
 
Do you know...LinFu?

GeneralNice ProjectmemberAkash Kava22-Sep-07 8:55 
Hi,
 
I must appriciate for your efforts, really great work!! indeed looks like microsoft copied your stuff but belive me XAML of WPF sucks, no body is ever aware from where the theme or style will get loaded and which event will get fired when. Also WPF needs .NET 3.0 which does not support windows 2000 etc.
 
Your stuff is good, it runs on .NET 2.0, only problem right now is, no body wants to be microsoft hostage, we really need systems for non windows platforms and if you come up with java solution or some system independent like xul concept, you can have a real nice future for your this project. We are currently in dead need for such project where it is system independent and gives features like yours, which can easily consume web services.
 
If you have any such plans please let us know, I have good knowledge of .Net and Java both, if I can contribute anything please let me know.
 
Thank you,
 
Programming is fun.
-Akash Kava

GeneralCan't installmemberGreg Roberts21-Nov-06 15:44 

Marc
 
First of all thanks
 
The earlier version won't install because my version of .net 2.0 is after the one it wants
 
When i try the later sample and manually install files it does not find
classes Cifton and Vts
 
I am using vs2005
 
Thanks
Questionwhat about BAML files?memberStanimir_Stoyanov23-Jul-04 2:38 
Hi!
I really like Longhorn stuff, and XAML. But I know there are also BAML files - compiled XAML's
Can someone tell me some info about such files, and is there a thing like 'BAML reader', tool to convert or only read such files?
 
Thanks in advance,
Stan
GeneralExcellentmemberBrian Delahunty1-Jun-04 2:36 
Excellent article and cool project. Big Grin | :-D
 
Regards,
Brian Dela Smile | :)
 
http://www.briandela.com IE 6 required.
http://www.briandela.com/pictures Now with a pictures section Big Grin | :-D
http://www.briandela.com/rss/newsrss.xml RSS Feed
QuestionDynamic wizard - Is this possible?memberjvoelcker24-Mar-04 5:35 
I am still trying to get my head around how this works, so please excuse my ignoranceSmile | :)
 
I want to create a winforms app that contains a dynamic wizard style questionnaire that presents the user with a series of questions (several per screen) and then saves the answers to an XML file.
 
OK, as far as I can understand this is pretty straight forward, however to add an extra layer of complexity I want to be able to able to...
 
a. be able to load the data from a previous questionnaire at the start of the wizard and then allow the user to run the wizard to change it.
 
b. Include so dynamic logic so that the answer to a question on one screen can determine the questions to be asked on the next.
 
c. be able to alter any of the logic or questions, etc by updating the back end xml file
 
Is this achievable using MyXAML?
 
Do you forsee any major difficulties?
 
Any pointers would be appreciated.
 
Cheers,
 
Julian Voelcker
AnswerRe: Dynamic wizard - Is this possible?editorMarc Clifton24-Mar-04 7:12 
Hi Julian,
 
(While I replied directly, I figure posting a reply on the message board would be good too!)
 
Well, MyXaml is a static user interface generator. So, to make the content dynamic, your application would have to generate the markup, then give it to the MyXaml parser.
 
However, there are a few possibilities to consider as well.
 
If the logic for selecting the questions has "screen granularity" (so that you pick which screen to use for the appropriate set of questions), then you could code all your question screens in XAML and the application would contain the underlying logic to select the next appropriate screen (and therefore the next set of questions).
 
Now, basically, that's just a large state map. If the answers to the questions on screen 1 are A A A A, then display screen 2. If the answers on screen 1 are A A A B, then display screen 3, and so forth. You probably don't actually have a different screen for every permutation, but you get the idea.
 
Jorgen is writing a state machine that will do exactly what you want--given the current state (which screen am I on?) and a set of rules (what were the answers?) transition to the next appropriate state (the appropriate second screen of questions).
 
Then, you can specify the screens in XAML, the state diagram in XAML, and if you need to change it, you can edit the XAML. Your code would essentially consist of an event handler to bring up the next screen in the wizard and to log the answers.
 
Does that make sense?
 
Marc

 
Microsoft MVP, Visual C#
MyXaml
MyXaml Blog
GeneralRe: Dynamic wizard - Is this possible?memberjvoelcker24-Mar-04 8:42 
Hi Marc,
 
Thanks for the prompt response - yes it does make a lot of sense.
 
Yes, the logic for selecting the questions has "screen granularity" so I should be OK there.
 
Jorgen's state machine also sounds perfect - do you know how far down the line is he with it?
 
I'll have a bit more of a play with the demo code in the morning and then might get back to you with some more questions.
 
Do you want feedback here or on the new forums?
 
Cheers,
 
Julian
GeneralRe: Dynamic wizard - Is this possible?editorMarc Clifton24-Mar-04 9:59 
jvoelcker wrote:
Do you want feedback here or on the new forums?
 
On the MyXaml forum would be nice. Big Grin | :-D
 
Marc
 
Microsoft MVP, Visual C#
MyXaml
MyXaml Blog
QuestionA similar project?memberpjholden7710-Mar-04 17:02 
Don't know if anybody else has seen this, but it looks similar to what MyXaml is doing.
 
http://windowsforms.net/articles/wfml.aspx
AnswerRe: A similar project?editorMarc Clifton10-Mar-04 17:15 
pjholden77 wrote:
Don't know if anybody else has seen this, but it looks similar to what MyXaml is doing.
 
Yup. Except I have style sheets, data binding, data sources, object referencing, in-line and code-behind coding, inline data sources, etc.
 
And I'm adding new features every day. Big Grin | :-D
 
Marc
 
Microsoft MVP, Visual C#
GeneralRe: A similar project?memberP Holden11-Mar-04 0:31 
I haven't had the chance to look at either solution in detail, but it does seem as though MyXaml covers a lot more than WFML and looks simpler in it's implementation.
Hopefully I'll get a bit of time to look through it all soon as I'm probably goin to start looking at using Tim Dawson's Hosting Designers article with MyXaml for a pet project of mine.
If I get anything useful working I'l pass it on.
 
Great work, what I've read/seen so far is very impressive.
QuestionDo you have a UI designer?memberLiu Junfeng9-Mar-04 23:29 
Do you have a UI designer which can generate XAML?

AnswerRe: Do you have a UI designer?editorMarc Clifton10-Mar-04 2:53 
Liu Junfeng wrote:
Do you have a UI designer which can generate XAML?
 
Not yet. The closest thing is the Form2Xml converter that will take forms created in Visual Studio's designer and convert them to Xaml.
 
Marc
 
Microsoft MVP, Visual C#
QuestionSupport for custom canvas types?memberMichael P Butler9-Mar-04 2:15 
I have a class (DataForm) that derives from System.Windows.Forms.
 
It is located in a MyForms.dll assembly under a MyForms namespace.
 
I'd like to use this as a Canvas Type, using DataForm instead of Form.
 
Does the code support this. By replacing the System.Windows.Forms xmlns with my assembly. I can get the custom canvas created, and by using the System.Windows.Forms as a custom namespace, I can created the standard Windows controls on the form. However I can't use MainMenu or TabPage Canvas (obviously because my MyForms assembly doesn't have them)
 

 
Michael
 
But you know when the truth is told,
That you can get what you want or you can just get old,
Your're going to kick off before you even get halfway through.
When will you realise... Vienna waits for you?
- "The Stranger," Billy Joel

GeneralLoading FailsmemberKatamneni6-Mar-04 18:21 
I'm trying to use MyXAML gui generator to create my user interface.One of control resides in the assembly MyCompany.MyProject.MyControl.dll and depends on some other assmblies like MyCompany.MyProject.MyUtils.dll.When i tried create the control using MyXAML,it's failing to load the control even though all the dependency assemblies are avialable in the local folder.Can anybody help me to figure out the problem?
 

Thank You
GeneralRe: Loading FailseditorMarc Clifton7-Mar-04 2:54 
Katamneni wrote:
Can anybody help me to figure out the problem?
 
Are all the assemblies in the same folder?
 
You may need to reference the referenced assemblies in the UI tag, like:
 
xmlns:lib1="OOGroup.Windows.Forms, ImageButton, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
 
This would be a good test to see if the XGG can actually find the referenced assembly on its own. Make sure you specify the correct version and PublicKeyToken, if it's a strong named assembly.
 
Lastly, I have been dealing with the following problem. I don't think this is the problem you are having, but I thought I'd add it in here for completeness.
 
1. I have a Xaml loader in folder A that has been associated with .xaml file extensions.
2. I double click on .xaml file in folder B
3. the Xaml file references another assembly (like above), also found in folder B
 
Everything works fine until a call to the referenced assembly is made. Because of the way the Assembly load process works in the ApplicationDomain, only directories and subdirectories under folder A are searched, even though the XGG was able to find the referenced assembly!
 
Solution:
 
1. put a copy of the referenced assembly in folder A
2. strong name the referenced assembly and put it in the GAC
3. override AssemblyResolve event and load the assembly manually. For example:
 
Assembly AssemblyResolveEventHandler(object sender, ResolveEventArgs args)
{
  string path=Environment.CurrentDirectory+"\\";
  Assembly assembly=null;
  string assemblyName=StringHelpers.LeftOf(args.Name, ',');
  assembly=Assembly.LoadFrom(path+assemblyName+".dll");
  return assembly;
}
 
If none of that helps, let me know and we'll pursue some other means of figuring out the problem.
 
Marc
 
Microsoft MVP, Visual C#
GeneralRe: Loading FailsmemberKatamneni7-Mar-04 17:58 
Thank you sir,
So ,we need to specify all the dependecies recursively till it can resolve the dependencies itself.Right?One more doubt...
 
xmlns:lib1="OOGroup.Windows.Forms, ImageButton, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null".In this namespace definition,what's meant by having OO before namespace start?
 
Thank you once again.
GeneralRe: Loading FailseditorMarc Clifton9-Mar-04 4:00 
Katamneni wrote:
So ,we need to specify all the dependecies recursively till it can resolve the dependencies itself.Right?One more doubt...
 
I believe this is correct. Let me know if you continue to have problems.
 

Katamneni wrote:
In this namespace definition,what's meant by having OO before namespace start?
 
None. It was just the name of the namespace that the author used. If it was in the download or the article text, it was there by mistake. Frown | :( The ImageButton is a nice XP button that supports images that I'm referencing in some Xaml for a client. Here's the article on it: http://www.codeproject.com/cs/miscctrl/MgXpImageButton.asp[^]
 
Marc
 
Microsoft MVP, Visual C#
Generalanother more suggestionmemberIsmaelj4-Mar-04 5:43 
The first incarnation of the project was "neat" XML, and with the new additions has become a little bit "dirty" file.
 
What about putting appart dessing (the XML related to the look'n'feell of the form, equivalent to CSS in HTML parlance) and behabior (the code-behind or inline, references, etc) on separate files?
 
On complex applications this will really help. As a system administrator, I'm thinking on using your code to build .NET scripts as I do know with HTA and WSH/WSF where I've developed a custom framework witch let me do this kind of developments.
 
Ismael
GeneralRe: another more suggestioneditorMarc Clifton4-Mar-04 6:42 
Ismaelj wrote:
What about putting appart dessing (the XML related to the look'n'feell of the form, equivalent to CSS in HTML parlance) and behabior (the code-behind or inline, references, etc) on separate files?
 
This can be handled with the "def:CodeBehind" tags, as illustrated in the TabPage2 and TabPage4 canvases. I'm also working on additional tags that let you declare an assembly and class instance to instantiate at runtime that handles the events. The inline code is there simply because, well, "it can be done".
 
Also, all the code-behind (the event handlers, basically) can be handled by the application's instance, which it can pass to the generator. In that case, that instance receives all the event notifications, unless overridden with inline or code-behind AND the event is declared to use the code-behind class, as described in the article.
 
Marc
 
Microsoft MVP, Visual C#
GeneralExcelent, as usual :)memberDan Bunea3-Mar-04 3:05 
Hi,
 
As usual , another excelent article.
 
I am very intereseted in unit tesing windows.forms and in writing after I come to some conclusions about it a small article here on codeproject. Could you help me a little with some sugestions etc? I am a big fan of Test Driven Development, but there aren't too many articles around the net about unit testing desktop apps.
 
Thank you,
Dan
GeneralRe: Excelent, as usual :)editorMarc Clifton3-Mar-04 4:01 
Hi Dan,
 
thanks for the comments!
 
About unit testing windows.forms, that's certainly an aspect of unit testing that is currently under-served. It's very difficult, I think, to test the presentation layer. You can test up to the PL, but how do you really verify even simple state things--for example, making a selecting in a combobox changes the enabled or visible state of other controls?
 
My thinking along these lines is that you need a good architecture to support unit testing the PL. The MVC model is an example of an architecture that makes itself amenable to PL unit tests, because you can set states in the model which fires events in the view, then inspect the view. Similarly, you can change PL state and/or simulate PL events, which the view receives, is processed by the controller, and changes state in the model, which you can then inspect with a unit test.
 
This is the approach I would take. Like other aspects of unit testing, I have found that you need a good architecture to really leverage the benefits of unit testing.
 
A good example of an MVC model is buried in my article on an event pool[^].
 
Also, why don't you join my Advanced Unit Testing[^] open source effort? Which is based on my articles on--unit testing[^]. Also, I think PL unit tests would make for some good additions to Unit Test Patterns.[^]
 
Hope to see you on the AUT project!
 
Marc
 
Microsoft MVP, Visual C#
GeneralRe: Excelent, as usual :)memberDan Bunea3-Mar-04 4:27 
Hi Marc,
 
Thank you for your answer. As I used to be J2EE programmer in the past, MVC is very widely used in Java so I portd it to my windows.forms applications. Each Form is a view, the behaviour is contolled my a Controller class and data and access to Business Layer is made throught a Model class. As you said that gave me possiblities for unit testing, and I could easely test some logic, like when a List (ListView) of
invoices is empty to disable the delete button.
 
Sometimes, my tests even include testing when the form is shown (invalidation and repaint seems to be problematic) like:
 

Public Sub TestNext()
Dim form As New Form2()
form.Show()
 
For index = 0 To 100
 
start = DateTime.Now()
form.Controller.OnNext()
Next

 
...
 

End Sub
 
I am thinking in firing the events (like button click) from the test, but I did not have time to explore this possiblity.
 
I have evaluated TestComplete 3.0 (AutomationQA) but I am still thinking of making traditional unit testing (I use NUnit).
 
I would gradly join a group on unit testing , I did not know about it so far.
 
Thank you again,
Dan
 

GeneralA small questionmemberWillemM29-Feb-04 21:18 
I noticed that references to controls aren't supported.
Am I right here, or am I doing something wrong? I have the following XML:
 
<pre><Canvas Name='MainForm' Size='100,100' AcceptButton='btnOk' FormBase='Form'>
   <Controls>
      <Button Name='btnOk' Size='150,21' Location='10,10' DialogResult='OK'/>
   </Controls>
</Canvas></pre>
 
The dialogresult property sets just fine, but the AcceptButton property doesn't... It doesn't give an error either.
Not that this is a really big problem, but it could be nice in the future to support control references.
 
Solution for now:
Add an event handler for the Load event and put in the following code:
 
<code language="C#">
private void OnLoad(object sender, EventArgs e)
{
   Form frm = (Form)sender;
  
   foreach(Button btn in frm.Controls)
   {
      if(btn.Name == "btnOk")
      {
         frm.AcceptButton = btn;
         break;
      }
   }
}
</code>
 
<b>Greetings.... Smile | :) </b><br>

GeneralRe: A small questioneditorMarc Clifton1-Mar-04 1:02 
This is something I'm working on. Looking at how this might be done in Longhorn, it seems that the reference would be made using the following syntax:
 
AcceptButton="{OKButton}"
 
where OKButton is the value of the NAME property of the button.
 
This should be a fairly straightforward modification to the attribute setter. The only glaring problem is that the parent control attributes are assigned before the child controls are instantiated. This will have to change--the parent control attributes have to be set *after* the child controls are instantiated.
 
I'll update the code shortly, as I am dealing with this very same problem!
 
Marc
 

 
Microsoft MVP, Visual C#
GeneralRe: A small questionmemberWillemM1-Mar-04 2:03 
great, if you have time Smile | :)
The rest of the stuff works just fine the way it is!
 
Greetings.... Smile | :)


GeneralRe: A small questioneditorMarc Clifton1-Mar-04 11:31 
WillemM wrote:
great, if you have time
 
object references added!
 
Hit refresh on the browser to update the screenshot.
 
Marc
 
Microsoft MVP, Visual C#
GeneralRe: A small questionmemberWillemM1-Mar-04 19:58 
Thanks a lot Smile | :)
 
Greetings.... Smile | :)


GeneralMore suggestionsmemberIsmaelj28-Feb-04 6:29 
Very great job, just what I've been looking for since .Net was released!
 
I have three suggestions for the project:
 
1- A web counterpart: the interpreter can generate the code for an aspx or a winform
 
2- A "compiled" or "cached" form: once it has been generated, it's compiled to a separate assembly. Anytime the program loads it checks the xml version and if it changed is reloaded and compiled, otherwise it's loaded from the binary file.
 
3- I think this is a really good project in which many other people we'll be interested to work with, so a web page centralizing your article's updates and contributions will help us.
 
Wink | ;) Hope you will like to implement some of these!
GeneralRe: More suggestionsmemberleppie28-Feb-04 7:52 
Ismaelj wrote:
I think this is a really good project in which many other people we'll be interested to work with, so a web page centralizing your article's updates and contributions will help us.
 
I agree this has good potential Smile | :)
 
top secret
GeneralOne comment on new versionmemberchris Liang27-Feb-04 10:24 
Great work!!!!
I feel the xml schema is more like the control structure of MS Access than XAML:
<Control>
<Properties>
<Property />
</Properties>
<Controls>
<Control/>
</Controls>
<Events>
<Event/>
</Events>
</Control>
 
I like the old version!
 

GeneralSourcememberVicente27-Feb-04 8:03 
Excellent work I must say! But.. it seems that the current source doesn't match the current article?

 
Religion is for the brain what tapeworm is for the stomache
GeneralRe: SourcememberVicente27-Feb-04 8:06 
oops! My bad! Seems to be the correct version now! Smile | :)
GeneralWowsersmemberWillemM26-Feb-04 22:02 
Yeah man, your good!
This is exactly what I am looking for, xaml for windows 2000/XP Smile | :) not only for longhorn.
 
Greetings.... Smile | :)


GeneralExceptionmemberDante Otero26-Feb-04 4:22 
I am having a System.InvalidCastException when executing the following line:
 
form=(System.Windows.Forms.Control)InstantiateControl(formNode.NamespaceURI, formBaseName);
 
more details: it's line 305 in XMLGuiGenerator.cs , i've ported the solution to VS.NET 2002.
 
Any suggestions?
 

Thanks in advance...
GeneralRe: ExceptioneditorMarc Clifton26-Feb-04 4:33 
Dante Otero wrote:
Any suggestions?
 
Well, only in the sense of general guidance.
 
First, I think there are some differences in what VS.NET 2002 supports in terms of XPath compared to 2003, but that may not be your problem.
 
Is the namespace valid? Is the formBaseName something derived from Control?
 
If you trace into the function, is "Type t=..." valid?
 
Does "ctrl=Activator.CreateInstance" work?
 
I suspect it's failing somewhere there. Technically, I shouldn't even being doing the (System.Windows.Form.Control) cast, and it will be removed in the next update.
 
If you want, you can also email me the XML file you're using and I'll see if it happens with 2003.
 
Marc
 
Microsoft MVP, Visual C#
GeneralExcellent!!!memberRajesh Pillai25-Feb-04 17:02 
Excellent article Marc!!! Nice job again..
 
Enjoy Coding,
GeneralNice jobsussEduardo Miranda25-Feb-04 13:36 
Marc,
 
Very good article you put togheter. I was actually trying to do something like that, and you gave me a boosted start-up.
 
I will refactor your sample to cover all my requirements.
 
Thank you very much.
 
Eduardo Miranda
GeneralRe: Nice jobeditorMarc Clifton25-Feb-04 14:42 
Thanks for the feedback. I'm curious, as I'd like to keep developing this, what your requirements are, if you can divulge them.
 
Marc
 
Microsoft MVP, Visual C#

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130619.1 | Last Updated 10 Mar 2004
Article Copyright 2004 by Marc Clifton
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid