Benjamin
Benjamin

Reputation: 15

Deserializing XML into C# so that the values can be edited and re-serialized again

I put together a windows form with some(a lot of)help from my previous question, which can be found here, this form takes two values from a textbox and stores them in a tuple and this tuple is stored as the value of a dictionary, while the key of the dictionary is taken from a third textbox. The form is capable of serializing the dictionary keyvaluepairs into a XML file, but I am having hard time to deserialize the XML file so that the keyvaluepairs could be edited and re-serialized. I have three buttons Add Submit and Edit, Add adds the user entered values into the dictionary, Submit serializes the dictionary keyvaluepairs and Edit would deserialize the XML file. I am using Microsoft Visual Studio 2010 with C#.

Summary of questions:

  1. How do I deserialize my XML file
  2. How do I edit the keyvaluepairs (possibly with the use of a list box)
  3. How to re-serialize (not sure if I could use my current current serialization code)

I would like my Edit button deserialize the XML file by clicking on it, once clicked I would like the keyvaluepairs to be listed in the listbox(listbox1) I have set up and if one of the keyvaluepairs has been clicked on, that specific value pair should be inserted into the three corresponding textboxes from where if the user edits the value(s) the Add button could be used to add the updated values back into the listbox from where using the Submit button the value pairs could be re-serialized.

If i wasn't clear or if you need a better understanding please let me know so I can clarify.

I will include the simplified code below just so it will be easier to understand what I would like to do:

    namespace Test1
    {
        public partial class Adding : Form
        {
            Dictionary<string, Tuple<int, int>> d = new Dictionary<string, Tuple<int, int>>();

            public Adding()
            {
                InitializeComponent();
            }

            public void btn_Add_Click(object sender, EventArgs e)
            {
                //Declare values for Tuple and Dictionary
                int X_Co = Convert.ToInt32(XCoordinate.Text);
                int Y_Co = Convert.ToInt32(YCoordinate.Text);
                string B_ID = Convert.ToString(BeaconID.Text);

                //Create new Tuple
                var t = new Tuple<int, int>(X_Co, Y_Co);

                //Add Beacon ID and X,Y coordinates from the tuple into the dictionary
                if (!d.ContainsKey(B_ID))
                {
                    d.Add(B_ID, t);//Make sure keys are unique
                }
                else
                {
                    MessageBox.Show("Key already exists please enter a unique key.");
                }
                //Display dictionary values in the listbox
                listBox1.DataSource = new BindingSource(d, null);
                listBox1.DisplayMember = "Key,Value";
                //listBox1.ValueMember = "Key";
            }

            public void btn_Submit_Click(object sender, EventArgs e)
            {
                List<Coordinate> cv = new List<Coordinate>();
                foreach (KeyValuePair<string, Tuple<int, int>> entry in d)
                {
                    Coordinate v = new Coordinate();

                    v.DateTime = DateTime.Now.ToString("dd/MM/yyyy hh/mm/ss");
                    v.BeaconID = entry.Key;
                    v.XCoordinate = entry.Value.Item1.ToString();
                    v.YCoordinate = entry.Value.Item2.ToString();
                    cv.Add(v);
                }
                SaveValues(cv);
                MessageBox.Show("Coordinates were exported successfully", "Message");
            }

            public void btn_Edit_Click(object sender, EventArgs e)
            {

            }

            public class Coordinate
            {
                public string DateTime { get; set; }
                public string BeaconID { get; set; }
                public string XCoordinate { get; set; }
                public string YCoordinate { get; set; }
            }

            public void SaveValues(List<Coordinate> v)
            {
                XmlSerializer serializer = new XmlSerializer(typeof(List<Coordinate>), new XmlRootAttribute("Coordinates"));
                using (TextWriter textWriter = new StreamWriter(@"F:\Vista\Exporting into XML\Test1\Coordinates.xml", true))
                {
                    serializer.Serialize(textWriter, v);
                }
            }
        }
    }

Thank you for any and every help.

Upvotes: 1

Views: 1277

Answers (1)

Matthew Watson
Matthew Watson

Reputation: 109712

You can read in your serialized list (if any) at the beginning of the program, and then update the list as necessary while the program runs.

When you want to save the data again, you can just re-serialize the updated list.

The following program demonstrates. It reads in a List<Coordinate> at the start (or initializes an empty list if the XML file doesn't exist).

Then it adds some more items to the list and prints out the BeaconID of the last-added item.

Finally it re-serializes the new list.

If you run this program a few times (after changing the filename to something suitable for your environment) you'll see that the list keeps getting bigger.

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;

namespace Demo
{
    public class Coordinate
    {
        public string DateTime { get; set; }
        public string BeaconID { get; set; }
        public string XCoordinate { get; set; }
        public string YCoordinate { get; set; }
    }

    public static class Program
    {
        public static void Main()
        {
            var date = DateTime.Now.ToString();

            string filename = "D:\\TMP\\TEST.XML";

            List<Coordinate> coords;

            // Deserialize the existing list or create an empty one if none exists yet.

            if (File.Exists(filename))
                coords = DeserializeFromFile<List<Coordinate>>(filename);
            else
                coords = new List<Coordinate>();

            // Add some new items to the list.

            int n = coords.Count;

            for (int i = 0; i < 5; ++i)
            {
                int j = n + i;

                coords.Add(new Coordinate
                {
                    DateTime    = date,
                    BeaconID    = "ID" + j,
                    XCoordinate = "X" + j,
                    YCoordinate = "Y" +j
                });
            }

            // Print the BeaconID of the last item in the list.

            Console.WriteLine(coords[coords.Count-1].BeaconID);

            // Save the amended list.

            SerializeToFile(coords, filename);
        }

        public static void SerializeToFile<T>(T item, string xmlFileName)
        {
            using (FileStream stream = new FileStream(xmlFileName, FileMode.Create, FileAccess.Write))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                serializer.Serialize(stream, item);
            }
        }

        public static T DeserializeFromFile<T>(string xmlFileName) where T: class
        {
            using (FileStream stream = new FileStream(xmlFileName, FileMode.Open, FileAccess.Read))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                return serializer.Deserialize(stream) as T;
            }
        }
    }
}

Upvotes: 1

Related Questions