Click here to Skip to main content
15,896,153 members
Articles / Programming Languages / C#

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

Rate me:
Please Sign up or sign in to vote.
4.81/5 (77 votes)
9 Mar 2004CPOL11 min read 398.5K   165  
Generate controls, set property values, and wire up event handlers at runtime from an XML definition.
/*
Copyright (c) 2004, Marc Clifton
All rights reserved.
Usage restricted under the terms of the BSD License conditions:
http://opensource.org/licenses/bsd-license.php
*/

using System;
using System.Collections;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Reflection;
using System.Xml;

namespace XmlGuiGenerator
{
	/// <summary>
	/// Manage the Object data type, include DataSource property setters.
	/// </summary>
	public class ObjectModel : PropertyModelBase
	{
		/// <summary>
		/// Set the control's property that takes a type "object".
		/// </summary>
		/// <param name="obj">The Control instance with an object type.</param>
		/// <param name="pi">The PropertyInfo instance.</param>
		/// <param name="val">The value, as a string.  If a DataSource is being set, then this specifies the property getter
		/// that returns the data source.  For forms that do not specify code-behind or inline code, this property getter
		/// must be supplied by the event target passed to the generator by the application.  In this case, the value is simply
		/// the name of the method.  Otherwise, the DataSource must be supplied by a class instantiated in the inline or code-behind code.
		/// In this case, it is of the form "className.methodName" where "className" is the name of a class defined in the inline or
		/// code-behind code.</param>
		/// <param name="target">Used only when setting a DataSource property (which is an object type).  In this case, this
		/// parameter specifies the target instance containing the DataSource field which must be accessible via a 
		/// property getter.</param>
		/// <returns>null</returns>
		public override object SetValue(object obj, PropertyInfo pi, string val, object target)
		{
			try
			{
				// oi!  A DataSource property takes a object parameter!
				if (pi.Name=="DataSource")
				{
					// val contains the property instance for the target!
					if (currentNode is XmlElement)
					{
						string[] colList;
						DataTable dt=new DataTable();
						XmlAttribute colAttr=currentNode.Attributes["columns"];
						if (colAttr != null)
						{
							// allows a whitespace delimited list of columns that overrides the default
							string columns=colAttr.Value;
							colList=columns.Split(' ');
						}
						else
						{
							colList=new string[] {"value", "text"};
						}

						foreach(string c in colList)
						{
							dt.Columns.Add(new DataColumn(c));
						}
						// the first column defaults to being the primary key
						dt.PrimaryKey=new DataColumn[] {dt.Columns[0]};

						foreach(XmlNode node in currentNode.ChildNodes)
						{
							DataRow row=dt.NewRow();
							foreach(string columnName in colList)
							{
								try
								{
									string text=node.Attributes[columnName].InnerText;
									row[columnName]=text;
								}
								catch(Exception e)
								{
									Trace.WriteLine("Error: Expected 'value' and 'text' attributes   "+e.Message);
								}
							}
							dt.Rows.Add(row);
						}
						pi.SetValue(obj, dt, null);
					}
					else
					{
						target=generator.GetTarget(ref val, target);
						PropertyInfo valPI=target.GetType().GetProperty(val);
						if (valPI != null)
						{
							// get the data in the target's property
							object data=valPI.GetValue(target, null);
							// set it in the control's property
							pi.SetValue(obj, data, null);
						}
						else
						{
							Trace.WriteLine("Unable to acquire property info for "+target.ToString()+"."+val);
						}
					}
				}
				else
				{
					pi.SetValue(obj, val, null);
				}
			}
			catch(Exception e)
			{
				Trace.WriteLine("ObjectModel: setter failed for: "+pi.ToString()+"   val="+val+"   "+e.Message);
			}
			return null;
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Architect Interacx
United States United States
Blog: https://marcclifton.wordpress.com/
Home Page: http://www.marcclifton.com
Research: http://www.higherorderprogramming.com/
GitHub: https://github.com/cliftonm

All my life I have been passionate about architecture / software design, as this is the cornerstone to a maintainable and extensible application. As such, I have enjoyed exploring some crazy ideas and discovering that they are not so crazy after all. I also love writing about my ideas and seeing the community response. As a consultant, I've enjoyed working in a wide range of industries such as aerospace, boatyard management, remote sensing, emergency services / data management, and casino operations. I've done a variety of pro-bono work non-profit organizations related to nature conservancy, drug recovery and women's health.

Comments and Discussions