How to deserialize and create a form on the fly

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • nodoid
    New Member
    • May 2010
    • 19

    How to deserialize and create a form on the fly

    Having a bit of fun here. I've read in a file in XML and deseralised it. Based on the contents of the XML file, I've generated a page on the fly (and it works).

    However, the XML file contains the data for more than one page to be generated. The idea is that you click the forward button, the event is fired and the new window generated.

    The deserialiser method passes the XML data to the winform generator directly which is then passed to the button click.

    The problem is this. I can't get it to move to the next set of data!

    Current code looks like this

    Code:
    namespace form_from_xml 
    {
        
        public class xmlhandler : Form
        {
            public void loaddesign()
            {
                FormData f;
                f = null;
    
                try
                {
                    string path_env = Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar;
                    XmlSerializer s = new XmlSerializer(typeof(FormData));
                    TextReader r = new StreamReader(path_env + "designer-test.xml");
                    f = (FormData)s.Deserialize(r);
                    r.Close();
                }
                catch (System.IO.FileNotFoundException)
                {
                    MessageBox.Show("Unable to find the form file", "File not found", MessageBoxButtons.OK);
                }
                catch (System.InvalidOperationException e)
                {
                    MessageBox.Show(e.ToString(), "Error", MessageBoxButtons.OK);
                }
                winformgen wf = new winformgen();
                wf.makeform(f, 1);
    		}
        }
    
        public class winformgen : Form
        {
            public void makeform(FormData f, int page)
            {
                Form form1 = new Form();
                Assembly asm = typeof(Form).Assembly;
                foreach (Elements fort in f.elements)
                {
                    System.Type tp = asm.GetType(fort.type);
                    Object m = Activator.CreateInstance(tp);
                    if (m is Control)
                    {
                        Control widget = (Control)m;
                        if (fort.forwardlink != 999 || fort.backlink != 999)
                        {
                            Button b = new Button();
                            if (fort.forwardlink != 999)
                            {
                                b.Name = "forward";
                                b.Location = new Point(fort.winxs - 100, fort.winys - 75);
                                b.Text = "Next >>";
                            }
                            else
                            {
                                b.Name = "backward";
                                b.Location = new Point(fort.winxs - 200, fort.winys - 575);
                                b.Text = "<< Back";
                            }
                            b.Height = 23;
                            b.Width = 75;
                            form1.Controls.Add(b);
                            b.Click += delegate(object s, EventArgs e) { ButtonClick(s, e, f, fort.pagenumber); };
                        }
    (nothing of any real interest happens after this point, just display the window)

    The click event looks like this

    Code:
            private void ButtonClick(object o, EventArgs e, FormData f, int page)
            {
                Control m = (Button)o;
                if (m.Name == "forward")
                    makeform(f, f.elements[page].forwardlink);
                else
                    makeform(f, f.elements[page].backlink);
            }
    It is in the same class as the form generator. The XML reader is in a completely different class (has to be for other reasons).

    There is nothing special about how the XML stuff is set up

    Code:
        [XmlRoot("Forms")]
        public class FormData
        {
            private ArrayList formData;
    
            public FormData()
            {
                formData = new ArrayList();
            }
    
    
            [XmlElement("Element")]
            public Elements[] elements
            {
                get
                {
                    Elements[] elements = new Elements[formData.Count];
                    formData.CopyTo(elements);
                    return elements;
                }
                set
                {
                    if (value == null)
                       return;
                    Elements[] elements = (Elements[])value;
                    formData.Clear();
                    foreach (Elements element in elements)
                        formData.Add(element);
                }
            }	    
    
            public int AddItem(Elements element)
            {
                return formData.Add(element);
            }
        }
     
        public class Elements
        {
            [XmlAttribute("formname")]
            public string fname;
            [XmlAttribute("winxsize")]
            public int winxs;
    The Elements class defines a pile of attributes and the instantates Elements with them.

    int page is pretty much ignored but needs to be used but I'm not sure how to. Any help would be appreciated.

    Paul
  • nukefusion
    Recognized Expert New Member
    • Mar 2008
    • 221

    #2
    Originally posted by nodoid
    Hi,

    Having a bit of fun here. I've read in a file in XML and deseralised it. Based on the contents of the XML file, I've generated a page on the fly (and it works).

    However, the XML file contains the data for more than one page to be generated. The idea is that you click the forward button, the event is fired and the new window generated.

    The deserialiser method passes the XML data to the winform generator directly which is then passed to the button click.

    The problem is this. I can't get it to move to the next set of data!

    Current code looks like this

    Code:
    namespace form_from_xml 
    {
        
        public class xmlhandler : Form
        {
            public void loaddesign()
            {
                FormData f;
                f = null;
    
                try
                {
                    string path_env = Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar;
                    XmlSerializer s = new XmlSerializer(typeof(FormData));
                    TextReader r = new StreamReader(path_env + "designer-test.xml");
                    f = (FormData)s.Deserialize(r);
                    r.Close();
                }
                catch (System.IO.FileNotFoundException)
                {
                    MessageBox.Show("Unable to find the form file", "File not found", MessageBoxButtons.OK);
                }
                catch (System.InvalidOperationException e)
                {
                    MessageBox.Show(e.ToString(), "Error", MessageBoxButtons.OK);
                }
                winformgen wf = new winformgen();
                wf.makeform(f, 1);
    		}
        }
    
        public class winformgen : Form
        {
            public void makeform(FormData f, int page)
            {
                Form form1 = new Form();
                Assembly asm = typeof(Form).Assembly;
                foreach (Elements fort in f.elements)
                {
                    System.Type tp = asm.GetType(fort.type);
                    Object m = Activator.CreateInstance(tp);
                    if (m is Control)
                    {
                        Control widget = (Control)m;
                        if (fort.forwardlink != 999 || fort.backlink != 999)
                        {
                            Button b = new Button();
                            if (fort.forwardlink != 999)
                            {
                                b.Name = "forward";
                                b.Location = new Point(fort.winxs - 100, fort.winys - 75);
                                b.Text = "Next >>";
                            }
                            else
                            {
                                b.Name = "backward";
                                b.Location = new Point(fort.winxs - 200, fort.winys - 575);
                                b.Text = "<< Back";
                            }
                            b.Height = 23;
                            b.Width = 75;
                            form1.Controls.Add(b);
                            b.Click += delegate(object s, EventArgs e) { ButtonClick(s, e, f, fort.pagenumber); };
                        }
    (nothing of any real interest happens after this point, just display the window)

    The click event looks like this

    Code:
            private void ButtonClick(object o, EventArgs e, FormData f, int page)
            {
                Control m = (Button)o;
                if (m.Name == "forward")
                    makeform(f, f.elements[page].forwardlink);
                else
                    makeform(f, f.elements[page].backlink);
            }
    It is in the same class as the form generator. The XML reader is in a completely different class (has to be for other reasons).

    There is nothing special about how the XML stuff is set up

    Code:
        [XmlRoot("Forms")]
        public class FormData
        {
            private ArrayList formData;
    
            public FormData()
            {
                formData = new ArrayList();
            }
    
    
            [XmlElement("Element")]
            public Elements[] elements
            {
                get
                {
                    Elements[] elements = new Elements[formData.Count];
                    formData.CopyTo(elements);
                    return elements;
                }
                set
                {
                    if (value == null)
                       return;
                    Elements[] elements = (Elements[])value;
                    formData.Clear();
                    foreach (Elements element in elements)
                        formData.Add(element);
                }
            }	    
    
            public int AddItem(Elements element)
            {
                return formData.Add(element);
            }
        }
     
        public class Elements
        {
            [XmlAttribute("formname")]
            public string fname;
            [XmlAttribute("winxsize")]
            public int winxs;
    The Elements class defines a pile of attributes and the instantates Elements with them.

    int page is pretty much ignored but needs to be used but I'm not sure how to. Any help would be appreciated.

    Paul
    Hi Paul,
    Some of your code samples are incomplete, for example. you haven't shown the implementations of forwardlink and backlink. Although I can probably guess what they do a complete example would help.

    Are you able to attach an example XML file plus the source? If so I'll look into it for you.

    Comment

    • nodoid
      New Member
      • May 2010
      • 19

      #3
      Hi,

      forward and backward call the delegate which disposes of the window and then calls the makeform method with the new page number...

      Full source (the loaddesign method is called from a button click)

      Code:
      using System;
      using System.Collections.Generic;
      using System.ComponentModel;
      using System.Data;
      using System.Drawing;
      using System.Windows.Forms;
      using System.IO;
      using System.Collections;
      using System.Xml;
      using System.Xml.Serialization;
      using System.Reflection;
      
      namespace form_from_xml 
      {
          
          public class xmlhandler : Form
          {
              public void loaddesign(int m)
              {
                  FormData f;
                  f = null;
      
                  try
                  {
                      string path_env = Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar;
                      XmlSerializer s = new XmlSerializer(typeof(FormData));
                      TextReader r = new StreamReader(path_env + "designer-test.xml");
                      f = (FormData)s.Deserialize(r);
                      r.Close();
                  }
                  catch (System.IO.FileNotFoundException)
                  {
                      MessageBox.Show("Unable to find the form file", "File not found", MessageBoxButtons.OK);
                  }
                  catch (System.InvalidOperationException e)
                  {
                      MessageBox.Show(e.ToString(), "Error", MessageBoxButtons.OK);
                  }
                  winformgen wf = new winformgen();
                  wf.makeform(f, 1);
      		}
          }
      
          public class winformgen : Form
          {
              public void makeform(FormData f, int page)
              {
                  Form form1 = new Form();
                  Assembly asm = typeof(Form).Assembly;
                  foreach (Elements fort in f.elements)
                  {
                      System.Type tp = asm.GetType(fort.type);
                      Object m = Activator.CreateInstance(tp);
                      if (m is Control)
                      {
                          Control widget = (Control)m;
                          if (fort.forwardlink != 999 || fort.backlink != 999)
                          {
                              Button b = new Button();
                              if (fort.forwardlink != 999)
                              {
                                  b.Name = "forward";
                                  b.Location = new Point(fort.winxs - 100, fort.winys - 75);
                                  b.Text = "Next >>";
                              }
                              else
                              {
                                  b.Name = "backward";
                                  b.Location = new Point(fort.winxs - 200, fort.winys - 575);
                                  b.Text = "<< Back";
                              }
                              b.Height = 23;
                              b.Width = 75;
                              form1.Controls.Add(b);
                              b.Click += delegate(object s, EventArgs e) { ButtonClick(s, e, f, fort.pagenumber, form1); };
                              
                          }
                          if (fort.type != "System.Windows.Forms.PictureBox" && fort.type != "System.Windows.Forms.RichTextBox")
                          {
                              widget.Text = fort.text;
                              widget.Location = new Point(fort.xpos, fort.ypos);
                              widget.Height = fort.ysize;
                              widget.Width = fort.xsize;
                              widget.Name = fort.name;
                              form1.Controls.Add(widget);
                          }
                          if (fort.ev == true)
                          {
                              widget.Click += new System.EventHandler(this.widget_Click);
                          }
                          if (fort.type == "System.Windows.Forms.PictureBox" && fort.external == false && fort.externalplace != "")
                          {
                              PictureBox b = new PictureBox();
                              b.Location = new Point(fort.xpos, fort.ypos);
                              b.Name = fort.name;
                              b.Height = fort.ysize;
                              b.Width = fort.xsize;
                              b.SizeMode = PictureBoxSizeMode.StretchImage;
                              b.Image = Image.FromFile(fort.externalplace);
                              form1.Controls.Add(b);
                          }
                          if (fort.type == "System.Windows.Forms.RichTextBox" && fort.external == false && fort.externalplace != "")
                          {
                              RichTextBox b = new RichTextBox();
                              b.Location = new Point(fort.xpos, fort.ypos);
                              b.Name = fort.name;
                              b.Height = fort.ysize;
                              b.Width = fort.xsize;
                              b.ReadOnly = true;
                              b.LoadFile(fort.externalplace);
                              form1.Controls.Add(b);
                          }       
                      }
                  }
                  form1.FormBorderStyle = FormBorderStyle.FixedDialog;
                  form1.MaximizeBox = false;
                  form1.MinimizeBox = false;
                  form1.StartPosition = FormStartPosition.CenterScreen;
                  form1.Width = f.elements[page].winxs;
                  form1.Height = f.elements[page].winys;
                  form1.Text = f.elements[page].title;
                  form1.Show();
              }
      
              private void widget_Click(object o, EventArgs e)
              {
                  MessageBox.Show("Hello", "Hello", MessageBoxButtons.OK);
              }
      
              private void ButtonClick(object o, EventArgs e, FormData f, int page, Form f1)
              {
                  Control m = (Button)o;
                  if (m.Name == "forward")
                  {
                      f1.Dispose();
                      makeform(f, f.elements[page - 1].forwardlink);
                  }
                  else
                  {
                      f1.Dispose();
                      makeform(f, f.elements[page - 1].backlink);
                  }
              }
          }
      
          [XmlRoot("Forms")]
          public class FormData
          {
              private ArrayList formData;
      
              public FormData()
              {
                  formData = new ArrayList();
              }
      
      
              [XmlElement("Element")]
              public Elements[] elements
              {
                  get
                  {
                      Elements[] elements = new Elements[formData.Count];
                      formData.CopyTo(elements);
                      return elements;
                  }
                  set
                  {
                      if (value == null)
                         return;
                      Elements[] elements = (Elements[])value;
                      formData.Clear();
                      foreach (Elements element in elements)
                          formData.Add(element);
                  }
              }	    
      
              public int AddItem(Elements element)
              {
                  return formData.Add(element);
              }
          }
       
          public class Elements
          {
              [XmlAttribute("formname")]
              public string fname;
              [XmlAttribute("winxsize")]
              public int winxs;
              [XmlAttribute("winysize")]
              public int winys;
              [XmlAttribute("wintitle")]
              public string title;
              [XmlAttribute("type")]
              public string type;
              [XmlAttribute("xpos")]
              public int xpos;
              [XmlAttribute("ypos")]
              public int ypos;
              [XmlAttribute("xsize")]
              public int xsize;
              [XmlAttribute("ysize")]
              public int ysize;
              [XmlAttribute("name")]
              public string name;
              [XmlAttribute("externaldata")]
              public bool external;
              [XmlAttribute("externalplace")]
              public string externalplace;
              [XmlAttribute("text")]
              public string text;
              [XmlAttribute("questions")]
              public bool questions;
              [XmlAttribute("questiontype")]
              public string qtype;
              [XmlAttribute("numberqs")]
              public int numberqs;
              [XmlAttribute("answerfile")]
              public string ansfile;
              [XmlAttribute("hasevent")]
              public bool ev;
              [XmlAttribute("backlink")]
              public int backlink;
              [XmlAttribute("forwardlink")]
              public int forwardlink;
              [XmlAttribute("pagenumber")]
              public int pagenumber;
      
              public Elements()
              {
              }
      
              public Elements(string fn, int wx, int wy, string wt, string t, int x, int y, int xs, int ys, string n, bool ext, 
                  string extpl, string te, bool q, string qt, int num, string ans, bool eve, int back, int end, int now)
              {
                  fname = fn;
                  winxs = wx;
                  winys = wy;
                  title = wt;
                  type = t;
                  xpos = x;
                  ypos = y;
                  xsize = xs;
                  ysize = ys;
                  name = n;
                  external = ext;
                  externalplace = extpl;
                  text = te;
                  questions = q;
                  qtype = qt;
                  numberqs = num;
                  ansfile = ans;
                  backlink = back;
                  ev = eve;
                  forwardlink = end;
                  pagenumber = now;
              }
          }
      }
      XML file

      Code:
      <?xml version="1.0" encoding="utf-8"?>
      <Forms>
      	<Element formname="Test Window" winxsize="800" winysize="350" wintitle = "The eye" 
      		type="System.Windows.Forms.PictureBox" xpos="25" ypos="50" xsize="300" ysize="200" name="pb1"
      		externaldata="false" externalplace="h:\eye.jpg" text="" questions="true" questiontype="none"
      		numberqs="0" answerfile="none" hasevent="false" backlink="999" forwardlink="999" 
      		pagenumber="1" />
      	<Element formname="Test Window" winxsize="800" winysize="350" wintitle = "The eye" 
      		type="System.Windows.Forms.RichTextBox" xpos="350" ypos="50" xsize="400" ysize="200" name="rt1"
      		externaldata="false" externalplace="h:\theeye.rtf" text="" questions="true" questiontype="none"
      		numberqs="0" answerfile="none" hasevent="false" backlink="999" forwardlink="2" 
      		pagenumber="1" />
      	<Element formname="Test Window" winxsize="800" winysize="350" wintitle = "The eye" 
      		type="System.Windows.Forms.PictureBox" xpos="25" ypos="50" xsize="300" ysize="200" name="pb1"
      		externaldata="false" externalplace="h:\eye.jpg" text="" questions="true" questiontype="none"
      		numberqs="0" answerfile="none" hasevent="false" backlink="999" forwardlink="999" 
      		pagenumber="2" />	
      	<Element formname="Test Window" winxsize="800" winysize="350" wintitle = "The eye" 
      		type="System.Windows.Forms.RichTextBox" xpos="350" ypos="50" xsize="400" ysize="200" name="rt1"
      		externaldata="false" externalplace="h:\theeye-lang.rtf" text="" questions="true" questiontype="none"
      		numberqs="0" answerfile="none" hasevent="false" backlink="1" forwardlink="999" 
      		pagenumber="2" />
      </Forms>
      Thanks

      Paul

      Comment

      • nodoid
        New Member
        • May 2010
        • 19

        #4
        One solution may be just to read in the data where pagenumber == page, but that would be slightly messy

        Something like

        XmlDocument doc = new XmlDocument();
        doc.Load(path_e nv + "designer-test.xml");
        f = doc.XmlSingleNo de("pagenumber" );

        though that would probably not really work as it would only read one set of data not multiple sets....

        Hmmm.....

        Comment

        • nukefusion
          Recognized Expert New Member
          • Mar 2008
          • 221

          #5
          Hi Paul,

          I've had a look at your code. Is the MakeForm method supposed to just read in the form data at the index specified by the page parameter? Because at the moment your doing a foreach loop over each element in the XML data and creating all the controls for each element, but adding them all to one form instance (form1).

          Code:
           public void makeform(FormData f, int page)
           {
                  Form form1 = new Form();
                  Assembly asm = typeof(Form).Assembly;
                  foreach (Elements fort in f.elements)
                  {
                      .... more code here adding controls.....
                     
                  }
                  form1.Show();
          
           }
          If the intention is to create one form at a time then remove the foreach loop and replace with:

          Code:
          Elements fort = f.elements[page];
          Does that make sense?

          Comment

          • nodoid
            New Member
            • May 2010
            • 19

            #6
            It does :-)

            However trying that only gives one thing in the window (in the first case, it's the text box). The XML has multiple objects on a form, but only the last is shown.

            I'm now thinking of setting up a simple for loop which counts how many objects there are with pagenumber == page and loop it through that way but again, that would cause another layer of problems unless I add another XML field with an object number counter on it...

            Hmmmmmm.....

            Comment

            • nukefusion
              Recognized Expert New Member
              • Mar 2008
              • 221

              #7
              Hi Paul,
              Ok, I've had a closer look at the XML and I see what you mean. If you want to de-serialize a single form with multiple elements then I think the issue is probably your XML structure. Currently it's unclear whether the Element node represents a Form, or a Control; it has attributes for both.

              Maybe a structure like the following would work better?

              Code:
              <Forms>
              	<Form name="Test Window" width="800" height="350">
              		<Element type="System.Windows.Forms.PictureBox" xpos="25" ypos="25" />
              		<Element type="System.Windows.Forms.TextBox" xpos="125" ypos="250" />		
              	</Form>
              	<Form name="Test Window 2" width="800" height="350">
              		<Element type="System.Windows.Forms.PictureBox" xpos="25" ypos="25" />
              		<Element type="System.Windows.Forms.TextBox" xpos="125" ypos="250" />		
              	</Form>
              </Forms>
              That's just a basic outline. You can add your other attributes in, adding any attributes that relate purely to the form to the Form node and anything that relates to the control only on the Element node.

              Comment

              • nodoid
                New Member
                • May 2010
                • 19

                #8
                It would probably make life simpler to do that, after all, get the XML deserialize bit correct and the rest should work.

                For your suggestion though, would the Elements class need to be re-written or is it enough just to restructure the XML?

                Comment

                • nukefusion
                  Recognized Expert New Member
                  • Mar 2008
                  • 221

                  #9
                  Originally posted by nodoid
                  It would probably make life simpler to do that, after all, get the XML deserialize bit correct and the rest should work.

                  For your suggestion though, would the Elements class need to be re-written or is it enough just to restructure the XML?
                  No, you'd need to adjust the Elements class too. I think I'd recreate the XML to map more closely what we are trying to store - a list of forms each with it's own list of elements.

                  I'd probably have one class for the Forms collection, let's call it FormsList to avoid confusion (there's already a FormsCollection class in the WinForms namespace)

                  Code:
                  using System;
                  using System.Collections.Generic;
                  using System.Linq;
                  using System.Xml.Serialization;
                  
                  namespace WindowsFormsApplication3
                  {
                      /// <summary>
                      /// A serializable collection of forms.
                      /// </summary>
                      [Serializable]
                      [XmlRoot("Forms")]
                      public class FormList
                      {
                          private IList<FormData> forms;
                  
                          /// <summary>
                          /// Initializes a new instance of the <see cref="Forms"/> class.
                          /// </summary>
                          public FormList()
                          {
                              forms = new List<FormData>();
                          }
                  
                          [XmlElement("Form")]
                          public FormData[] Forms
                          {
                              get { return this.forms.ToArray(); }
                              set { this.forms = new List<FormData>(value); }
                          }
                      }
                  }
                  Then a FormData class to represent the data from one form:

                  Code:
                  using System;
                  using System.Collections.Generic;
                  using System.Linq;
                  using System.Xml.Serialization;
                  
                  namespace WindowsFormsApplication3
                  {
                      /// <summary>
                      /// Represents a single form and the elements within it.
                      /// </summary>
                      [Serializable]
                      public class FormData
                      {
                          private IList<Element> elements;
                  
                          /// <summary>
                          /// Initializes a new instance of the <see cref="FormData"/> class.
                          /// </summary>
                          public FormData()
                          {
                              elements = new List<Element>();
                          }
                  
                          public string Name { get; set; }
                  
                          public int Width { get; set; }
                  
                          public int Height { get; set; }
                  
                          public string Title { get; set; }
                  
                          public int BackLink { get; set; }
                  
                          public int ForwardLink { get; set; }
                  
                          [XmlElement("Element")]
                          public Element[] Elements
                          {
                              get { return this.elements.ToArray(); }
                              set { this.elements = new List<Element>(value); }
                          }
                      }
                  }
                  Then a revised Element class:

                  Code:
                  using System;
                  using System.Xml.Serialization;
                  
                  namespace WindowsFormsApplication3
                  {
                      /// <summary>
                      /// Represents an element within a form.
                      /// </summary>
                      [Serializable]
                      public class Element
                      {
                          [XmlAttribute("Name")]
                          public string ElementName { get; set; }
                  
                          public int X { get; set; }
                  
                          public int Y { get; set; }
                  
                          public int Width { get; set; }
                  
                          public int Height { get; set; }
                  
                          public string Title { get; set; }
                  
                          public string Text { get; set; }
                  
                          [XmlAttribute("Type")]
                          public string ElementType { get; set; }
                   
                          /// <summary>
                          /// Initializes a new instance of the <see cref="Element"/> class.
                          /// </summary>
                          public Element()
                          {
                          }      
                      }
                  }
                  This would then serialize/deserialize an XML file like this:

                  Code:
                  <?xml version="1.0" encoding="utf-8" ?>
                  <Forms>
                    <Form Name="Test Window" Width="800" Height="350" Title="The eye 1" BackLink="" ForwardLink="2">
                      <Element Name="pb1" Type="System.Windows.Forms.PictureBox" X="25" Y="50" Width="300" Height="200" Text=""></Element>
                    </Form>
                    <Form Name="Test Window" Width="800" Height="350" Title="The eye 2" BackLink="" ForwardLink="2">
                      <Element Name="rt1" Type="System.Windows.Forms.RichTextBox" X="350" Y="50" Width="400" Height="200" Text=""></Element>
                    </Form>
                    <Form Name="Test Window" Width="800" Height="350" Title="The eye 1" BackLink="" ForwardLink="2">
                      <Element Name="pb1" Type="System.Windows.Forms.PictureBox" X="25" Y="50" Width="300" Height="200" Text=""></Element>
                    </Form>
                    <Form Name="Test Window" Width="800" Height="350" Title="The eye 2" BackLink="" ForwardLink="2">
                      <Element Name="rt1" Type="System.Windows.Forms.RichTextBox" X="350" Y="50" Width="400" Height="200" Text=""></Element>
                    </Form>
                  </Forms>
                  I think that probably represents the data you're trying to store better and using that format you should be able to solve your problem.

                  Comment

                  • nodoid
                    New Member
                    • May 2010
                    • 19

                    #10
                    Okay, no idea on this one. I've sorted a few other problems out, but the following is seriously annoying me as I can't see any valid reason for the error occuring...

                    Code:
                        [Serializable]
                        public class FormData
                        {
                            public List<Element> elements;
                            public FormData()
                            {
                                elements = new List<Element>();
                            }
                    
                            public string Name { get; set; }
                            public int Width { get; set; }
                            public int Height { get; set; }
                            public string Title { get; set; }
                            public int BackLink { get; set; }
                            public int ForwardLink { get; set; }
                            public int PageNumber { get; set; }
                    
                            [XmlElement("Element")]
                            public Element[] Elements
                            {
                                get { return this.elements.ToArray(); }
                                set { this.elements = new List<Element>(value); }
                            }
                        }
                    
                        [Serializable]
                        public class Element
                        {
                            [XmlAttribute("Name")]
                            public string ElementName { get; set; }
                            public int X { get; set; }
                            public int Y { get; set; }
                            public int Width { get; set; }
                            public int Height { get; set; }
                            public string Title { get; set; }
                            public string Text { get; set; }
                            
                            [XmlAttribute("Type")]
                            public string ElementType { get; set; }
                            
                            [XmlAttribute("External")]
                            public bool WithExternal { get; set; }
                            public string ExternalFile { get; set; }
                            
                            [XmlAttribute("Events")]
                            public bool HasClick { get; set; }
                            public bool HasWritable { get; set; }
                            public bool HasNumeric { get; set; }
                            
                            public Element()
                            {
                            }      
                        }
                    Code:
                    public List<Element> elements;
                    and
                    Code:
                    public Element[] Elements
                    are complaining that the type Element can't be found (am I missing a using directive).

                    Oh for the days of simple errors and other such things....

                    Comment

                    • nodoid
                      New Member
                      • May 2010
                      • 19

                      #11
                      Bloody visual studio 2008 - false positives... move along, nothing to see here...

                      Comment

                      • nodoid
                        New Member
                        • May 2010
                        • 19

                        #12
                        Okay, after a chunk of time on this I've come across two problems

                        1. The deserializer.

                        Currently it's using FormData to read in which gives an error as the first thing sucked in from the XML file is FormList. Okay, not a biggy, alter the references for FormData to FormList.

                        Ah. Problem. The foreach is annoyed at foreach (Element fort in f.Forms[].elements) - it's expecting a value in the brackets by the looks of it.

                        2. The XML format

                        Current code looks like this for the Elements class

                        Code:
                           [Serializable]
                            public class Element
                            {
                                [XmlAttribute("Name")]
                                public string ElementName { get; set; }
                                public int X { get; set; }
                                public int Y { get; set; }
                                public int Width { get; set; }
                                public int Height { get; set; }
                                public string Title { get; set; }
                                public string Text { get; set; }
                                
                                [XmlAttribute("Type")]
                                public string ElementType { get; set; }
                                
                                [XmlAttribute("External")]
                                public bool WithExternal { get; set; }
                                public string ExternalFile { get; set; }
                                
                                [XmlAttribute("Events")]
                                public bool HasClick { get; set; }
                                public bool HasWritable { get; set; }
                                public bool HasNumeric { get; set; }
                                public bool HasRO { get; set; }
                                
                                public Element()
                                {
                                }      
                            }
                        }
                        (I've added a few bits)

                        AIUI this would make the format of the XML like this

                        Code:
                        <forms>
                        <form // form definition />
                        <element>
                        <Name elementname="foo" // etc>
                        <Type elementtype="foo" />
                        <External // links to the outside world />
                        <HasEvents // event triggers />
                        </element>
                        // whatever is next in form
                        </form>
                        </forms>
                        Am I correct in thinking this or is my understanding still sketchy?

                        Comment

                        • nukefusion
                          Recognized Expert New Member
                          • Mar 2008
                          • 221

                          #13
                          The properties in the Elements class that have been decorated with the XmlAttribute metadata will be realised as attributes in the XML file. So it will look more like this:

                          Code:
                          <Element Name="" Type="" External="">
                          </Element>

                          Comment

                          • nodoid
                            New Member
                            • May 2010
                            • 19

                            #14
                            Ah. Okay, that makes some sense. What happens though with the bits declared within the attribute? Would it become

                            Code:
                            <Element Name="foo" ElementName="bar" X="100" Y="150" ...
                            followed by the other bits declared in Name then something similar for the other attributes or do I need to declare them some other way?

                            Comment

                            • nukefusion
                              Recognized Expert New Member
                              • Mar 2008
                              • 221

                              #15
                              The XmlAttribute only applies to the property it's immediately above; they're not grouped. By default, the properties will export as Nodes. With that class definition, what you'll get will be more like:

                              Code:
                              <Element Name="" Type="" External="" Events="">
                              	<X></X>
                              	<Y></Y>
                              	<Width></Width>
                              	<Height></Height>
                              	<Title></Title>
                              	<Text></Text>
                              	<ExternalFile></ExternalFile>
                              	<HasWritable></HasWritable>
                              	<HasNumeric></HasNumeric>
                              	<HasRO></HasRO>
                              </Element>

                              Comment

                              Working...