I use a xml based storage file in the application directory. here is my
class. Simply call SaveDesignToXML to save all settings and GetDesignFromXML
to load all settings. Relatively untested but feel free to use if you want.
----
using System;
using System.Windows.Forms;
using System.IO;
using System.Data;
namespace Adastra.GUI
{
/// <summary>
/// Summary description for Formscript.
/// </summary>
public class XMLFormscripting
{
private string xmlFilePath;
private string xmlBaseSchema;
private System.Windows.Forms.Form workingForm;
private DataSet ds;
/// <summary>
/// Constructor for Formscript Class
/// </summary>
/// <param name="form">The form of which we need to check for a file and
redesign the gui if one exists.</param>
public XMLFormscripting(System.Windows.Forms.Form form)
{
this.xmlFilePath = System.IO.Path.Combine(Application.StartupPath,
form.Name + ".xml");
this.xmlBaseSchema = System.IO.Path.Combine(Application.StartupPath,
"FormscriptBaseSchema.xsd");
this.workingForm = form;
if (File.Exists(xmlFilePath)) {
ds = new DataSet();
ds.ReadXml(xmlFilePath);
}
else if (File.Exists(xmlBaseSchema)) {
ds = new DataSet();
ds.ReadXmlSchema(xmlBaseSchema);
}
else {
// we need to cater for not having any appropriate files, so create one
and then reload into ds.
CreateLocalSchemaFile();
ds = new DataSet();
ds.ReadXmlSchema(xmlBaseSchema);
}
}
/// <summary>
/// CreateLocalSchemaFile - A method to protect ourselves from
programmatical error of not copying a file.
/// </summary>
private void CreateLocalSchemaFile() {
// the project did not have a local schema file to load, so create one
from raw text and it will mean
// if someone includes this in a project it will not go pop !
StreamWriter schemaFile = new StreamWriter(xmlBaseSchema,false);
schemaFile.WriteLine("<?xml version=\"1.0\" standalone=\"yes\" ?>");
schemaFile.WriteLine("<xs:schema id=\"Settings\" xmlns=\"\"
xmlns:xs=\"
http://www.w3.org/2001/XMLSchema\"
xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">");
schemaFile.WriteLine(" <xs:element name=\"Settings\"
msdata:IsDataSet=\"true\">");
schemaFile.WriteLine(" <xs:complexType>");
schemaFile.WriteLine(" <xs:choice maxOccurs=\"unbounded\">");
schemaFile.WriteLine(" <xs:element name=\"root\">");
schemaFile.WriteLine(" <xs:complexType>");
schemaFile.WriteLine(" <xs:sequence>");
schemaFile.WriteLine(" <xs:element name=\"ComponentName\"
type=\"xs:string\" minOccurs=\"0\" />");
schemaFile.WriteLine(" <xs:element name=\"Key\" type=\"xs:string\"
minOccurs=\"0\" />");
schemaFile.WriteLine(" <xs:element name=\"Value\"
type=\"xs:string\" minOccurs=\"0\" />");
schemaFile.WriteLine(" </xs:sequence>");
schemaFile.WriteLine(" </xs:complexType>");
schemaFile.WriteLine(" </xs:element>");
schemaFile.WriteLine(" </xs:choice>");
schemaFile.WriteLine(" </xs:complexType>");
schemaFile.WriteLine(" </xs:element>");
schemaFile.WriteLine("</xs:schema>");
schemaFile.Flush();
schemaFile.Close();
}
/// <summary>
/// GetDesignFromXML - method to allow the parsed form to be designed from
a saved xml file structure
/// </summary>
public void GetDesignFromXML() {
System.Windows.Forms.Control.ControlCollection ctrlCol =
workingForm.Controls;
foreach(DataTable t in ds.Tables){
foreach(DataRow r in t.Rows) {
// step through the dataset, locate the component it names.
string compName = (string)r["ComponentName"];
Control c = FindControl(null,compName);
if (c != null) {
string propName = (string)r["Key"];
switch (propName) {
case "Left":
c.Left = Convert.ToInt32(r["Value"]);
break;
case "Top":
c.Top = Convert.ToInt32(r["Value"]);
break;
case "Width":
c.Width = Convert.ToInt32(r["Value"]);
break;
case "Height":
c.Height = Convert.ToInt32(r["Value"]);
break;
case "Text":
c.Text = (string)r["Value"];
break;
} // switch
}
} // foreach(DataRow r in t.Rows)
} // foreach(DataTable t in ds.Tables
}
/// <summary>
/// SaveDesignToXML - Method allowing all current controls to be written
to an xml file for later parsing.
/// </summary>
public void SaveDesignToXML() {
System.Windows.Forms.Control.ControlCollection ctrlCol =
workingForm.Controls;
ds.Clear();
// Finally get properties for the form, and then save it all to the xml
file.
GetPropertiesForRowExport(workingForm, string.Empty);
ds.WriteXml(xmlFilePath, XmlWriteMode.WriteSchema);
}
/// <summary>
/// GetPropertiesForRowExport - Method to allow writing of a specific
controls properties to an xml file.
/// </summary>
/// <param name="c">an optional control to be parsed to output to
xml</param>
/// <param name="name">a string to pass, it is the prefix you want ie.
form1.panel.</param>
private void GetPropertiesForRowExport(Control c, string name) {
if (c != null) {
// Left Property
DataRow newRow1 = ds.Tables[0].NewRow();
newRow1["ComponentName"] = name + c.Name;
newRow1["Key"] = "Left";
newRow1["Value"] = Convert.ToString(c.Left);
ds.Tables[0].Rows.Add(newRow1);
// Top Property
DataRow newRow2 = ds.Tables[0].NewRow();
newRow2["ComponentName"] = name + c.Name;
newRow2["Key"] = "Top";
newRow2["Value"] = Convert.ToString(c.Top);
ds.Tables[0].Rows.Add(newRow2);
// Width Property
DataRow newRow3 = ds.Tables[0].NewRow();
newRow3["ComponentName"] = name + c.Name;
newRow3["Key"] = "Width";
newRow3["Value"] = Convert.ToString(c.Width);
ds.Tables[0].Rows.Add(newRow3);
// Height Property
DataRow newRow4 = ds.Tables[0].NewRow();
newRow4["ComponentName"] = name + c.Name;
newRow4["Key"] = "Height";
newRow4["Value"] = Convert.ToString(c.Height);
ds.Tables[0].Rows.Add(newRow4);
// Text Property
DataRow newRow5 = ds.Tables[0].NewRow();
newRow5["ComponentName"] = name + c.Name;
newRow5["Key"] = "Text";
newRow5["Value"] = c.Text;
ds.Tables[0].Rows.Add(newRow5);
}
if (c.Controls != null) {
foreach(Control c1 in c.Controls) {
if (c is Form) {
GetPropertiesForRowExport(c1, string.Empty);
}
else {
GetPropertiesForRowExport(c1, name + c.Name + ".");
}
}
}
}
/// <summary>
/// FindControl - function to locate a control, and any sub controls on
it.
/// </summary>
/// <param name="c">Control being parsed to check</param>
/// <param name="name">can be parsed Form1.Panel1.Panel2.TextBox1, we want
to return that exact control.</param>
/// <returns>the control that is returned.</returns>
private Control FindControl(Control c, string name) {
if (name.IndexOf(".") > 0) {
string[] splitStr = name.Split(".".ToCharArray(),2);
Control controlFound = FindControl(c,splitStr[0]);
return FindControl(controlFound, splitStr[1]);
}
else {
if (c != null) {
foreach(Control c2 in c.Controls) {
if (c2.Name == name) {
return c2;
}
}
}
else {
// the control parsed is null so we must just be dealing with the one
control on the form
foreach(Control c3 in workingForm.Controls) {
if (c3.Name == name) {
return c3;
}
}
if (workingForm.Name == name) {
// we should only get here if we have exhausted all other
possibilities.
return workingForm;
}
}
return null;
}
}
}
}