Click here to Skip to main content
15,895,781 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

I have used the XML serialization to save Text and a picture in a XML file. However, I am confused on how to extend the concept further.

I have a second Windows Form which has a TableLayoutPanel in which each cell has a Picture Box and a TextBox. The user has the option to set the number of rows and columns himself, so I do not know about the number of pictures that have to be saved in the XML file. Further, when the user pressed the load button, the same pictures have to come back to their original pictures boxes in the TableLayout.

How can I save the contents of the TableLayout in the XML file and retrieve them in their corresponding cells?

Here's the program that I have done till now.

http://www.mediafire.com/file/7f4dax0szsiaf4g/WindowsFormsApplication4.rar

Thanks for help.
Posted

K,
just i ll write the code..

add a class to your project by name "Output" and add the below code

XML
namespace YourNamespace
{
    class Output
    {
        int row;
        int column;
        List<Customer> person = new List<Customer>();
        public int Row
        {
            get { return row; }
            set { row = value; }
        }
        public int Column
        {
            get { return column; }
            set { column = value; }
        }
        public List<Customer> Person
        {
            get { return person; }
            set { person = value; }
        }
        public void Load(string path)
        {
            if (File.Exists(path))
            {
                Output o = ObjectXMLSerializer<Output>.Load(path);
                this.row = o.row;
                this.column = o.column;
                this.person = o.person;
            }
        }
        public void Save(string path)
        {
            ObjectXMLSerializer<Output>.Save(this, path);
        }
    }
}



then modify your Form1 (TableLayoutForm) class as follows

XML
namespace MSDNForums
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Output output = new Output();

        private void button1_Click(object sender, EventArgs e)
        {
            output.Person.Clear();
            output.Row = int.Parse(rowsTextBox.Text);
            output.Column = int.Parse(columnsTextBox.Text);

            tableLayoutPanel1.RowCount = int.Parse(rowsTextBox.Text);
            tableLayoutPanel1.ColumnCount = int.Parse(columnsTextBox.Text);

            for (int col = 0; col < tableLayoutPanel1.ColumnCount; col++)
            {
                for (int rows = 0; rows < tableLayoutPanel1.RowCount; rows++)
                {
                    Panel p = new Panel();
                    TextBox tb = new TextBox();
                    PictureBox picb = new PictureBox();
                    p.Controls.Add(tb);
                    p.Controls.Add(picb);
                    picb.Location = new Point(0, tb.Top + 20);
                    tableLayoutPanel1.Controls.Add(p, col, rows);

                    Customer c = new Customer();
                    c.Index = col * tableLayoutPanel1.RowCount + rows;
                }
            }
        }

        private void LoadPerson()
        {
            output.Load("output.out");

            tableLayoutPanel1.Controls.Clear();

            foreach (Customer c in output.Person)
            {
                int rows = c.Index / output.Column;
                int col = c.Index % output.Column;

                Panel p = new Panel();
                TextBox tb = new TextBox();
                PictureBox picb = new PictureBox();
                p.Controls.Add(tb);
                p.Controls.Add(picb);
                picb.Location = new Point(0, tb.Top + 20);
                tableLayoutPanel1.Controls.Add(p, col, rows);
            }
        }

        private void SavePerson()
        {
            output.Save("output.out");
        }
    }
}


you can use SavePerson and LoadPerson function to save and load the file.
If you still didnt get, then better i ll send you the full code :)
 
Share this answer
 
Comments
optimus_prime1 5-Oct-10 3:05am    
Thanks a lot for the efforts!
I needed to clarify somethings. Hope you won't mind answering them

In the Form1 code, wherever, I have used the Output class,
Output.Save("output.out");
Output.Person
Output.Load("output.out")

gives me an error:
Error: An object reference is required for the non-static field, method, or property 'YourNamespace.Output.Save(string)'
Yogesha Puttaswamy 5-Oct-10 3:39am    
Make the output class public
optimus_prime1 6-Oct-10 5:08am    
Hi,
Thanks!
Thanks a lot for the ingenious sample. I improvised the program a bit but Load is not operative correctly in my program.
Here's a sample program in which I tried things.
http://www.mediafire.com/?wcb4btj0p83zm5z

P.S Apart from this (off topic), if you could also look for slight modifications that might be needed in the program such as TableLayout Dock problem, anchor problem with controls, TableLayout Cell Width and Height adjustment, Fitting an image into the PicBox etc.
Sending the picture back to the picture box worked in my program. However, I wasn't able to send the Label back to the corresponding cell in which each it is contained (in Form1). Further, I have also have to send the Text from Form2 as PictureBox Tag in Form1.

I would be greatful for help.
Thanks a lot!
Hi,

Method 1:

You can add one more variable index(int) to your customer object, which keep track of the position of the customer(picture and text) in your TableLayoutPanel.

so your customer class becomes
<pre>
public class Customer
{
int index;
string CustomerName;
Bitmap Picture;
}
</pre>
then you can use list to store the cutomer objects added to your TableLayoutPanel.

List<Customer> customer_list;

while saving the list in Xml (Simple Serialization) you can change the index according to the position in the TableLayoutPanel and you can keep track.

Method 2:

Instead of adding index to your customer object, you can use Dictionary which contains the position and customer object.

Dictionary<int, Customer>

The problem is you cant Serialize Dictionary by the XmlSerializer. You have to create you own SerializableDictionary. I tried with my own class and it works. here is the code :

<pre>
[XmlRoot("dictionary")]
public class MyDictionary&lt;TKey, TValue&gt;
: Dictionary&lt;TKey, TValue, IXmlSerializable
{
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}

public void ReadXml(System.Xml.XmlReader reader)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

bool wasEmpty = reader.IsEmptyElement;
reader.Read();

if (wasEmpty)
return;

while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
{
reader.ReadStartElement("item");

reader.ReadStartElement("key");
TKey key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();

reader.ReadStartElement("value");
TValue value = (TValue)valueSerializer.Deserialize(reader);
reader.ReadEndElement();

this.Add(key, value);

reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}

public void WriteXml(System.Xml.XmlWriter writer)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

foreach (TKey key in this.Keys)
{
writer.WriteStartElement("item");

writer.WriteStartElement("key");
keySerializer.Serialize(writer, key);
writer.WriteEndElement();

writer.WriteStartElement("value");
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();

writer.WriteEndElement();
}
}
}
</pre>


Hope it helps you...
 
Share this answer
 
Comments
optimus_prime1 4-Oct-10 22:53pm    
"List<customer> customer_list;
while saving the list in Xml (Simple Serialization) you can change the index according to the position in the TableLayoutPanel and you can keep track."

Actually, I wasn't sure on how to change the index for different columns and rows in the TableLayout.
I would be really very thankful if you could modify the above program accordingly to save and load contents to make that evident.

Kindest Regards
Yogesha Puttaswamy 4-Oct-10 23:33pm    
create a class CustomerList(any name) which store the TableLayoutPanel.

public class CustomerList
{
int rowCount;
int columnCount;
List<customer> person = new List<customer>();
}

while you add a customer(picture and text) to your TableLayoutPanel, add same customer to the list person in above class.
Assign the Index of customer to = (CurrentRow * RowCount)+ColumnCount

while Reading, the position will be
(read the index of the customer object)
row = Index/ColumnCount;
column = index%ColumnCount;

Just i am converting (row,column) to a integer and reverse.
optimus_prime1 5-Oct-10 1:20am    
I know it feels like spoon feeding but I haven't been able to do it. I am not a pro and the learning process is still stumpy :( :(
It would be more valuable if you could amend the above sample (link in my original post) according to your notion.

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



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900