【问题标题】:Deserializing XML into C# so that the values can be edited and re-serialized again将 XML 反序列化为 C#,以便可以再次编辑和重新序列化值
【发布时间】:2015-02-13 12:36:38
【问题描述】:

我整理了一个 windows 表单,其中包含我上一个问题的一些(很多)帮助,可以找到 here,这个表单从一个文本框中获取两个值并将它们存储在一个元组中,这个元组存储为字典的值,而字典的键取自第三个文本框。该表单能够将字典键值对序列化为 XML 文件,但我很难反序列化 XML 文件,以便可以编辑和重新序列化键值对。我有三个按钮添加提交和编辑,添加将用户输入的值添加到字典中,提交序列化字典键值对,编辑将反序列化 XML 文件。我正在使用带有 C# 的 Microsoft Visual Studio 2010。

问题总结:

  1. 如何反序列化我的 XML 文件
  2. 如何编辑键值对(可能使用列表框)
  3. 如何重新序列化(不确定是否可以使用当前的序列化代码)

我希望我的编辑按钮通过单击它来反序列化 XML 文件,一旦单击,我希望键值对列在我设置的列表框 (listbox1) 中,如果已单击其中一个键值对,那特定的值对应插入三个相应的文本框中,如果用户编辑值,则添加按钮可用于将更新的值添加回列表框中,使用提交按钮可以重新添加值对序列化。

如果我不清楚或者您需要更好的理解,请告诉我,以便我澄清。

我将在下面包含简化的代码,以便更容易理解我想要做什么:

    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);
                }
            }
        }
    }

感谢您的任何帮助。

【问题讨论】:

    标签: c# xml winforms xml-serialization xml-deserialization


    【解决方案1】:

    您可以在程序开始时读取您的序列化列表(如果有),然后在程序运行时根据需要更新列表。

    当您想再次保存数据时,只需重新序列化更新的列表即可。

    以下程序演示。它在开始时读入List&lt;Coordinate&gt;(如果 XML 文件不存在,则初始化一个空列表)。

    然后它向列表中添加更多项目并打印出最后添加的项目的BeaconID

    最后它重新序列化新列表。

    如果您运行该程序几次(在将文件名更改为适合您环境的名称之后),您会发现列表越来越大。

    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;
                }
            }
        }
    }
    

    【讨论】:

    • 我试了一下,出现了错误。错误:未处理 InvalidOperationException XML 文档 (2, 2) 中存在错误。在“返回序列化程序...”这一行
    • @Benjamin 我刚刚注意到您正在附加到无法使用的 XML 文件(并且还使用 new XmlRootAttribute("Coordinates") 也无法使用)。您是否可以在程序开始时读取列表并将其附加到另一个列表中?
    • 如果你告诉我怎么做:)
    • @Benjamin 更新了我的答案。请注意,它仅解决了与序列化有关的部分问题。
    • @Benjamin 你编译并运行了我的示例程序吗?它当然对我有用,并且由于代码不同,它不可能在同一行上给出相同的错误...我希望您检查我发布的工作代码并将该方法应用于您的程序...
    猜你喜欢
    • 1970-01-01
    • 2012-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-12
    • 2010-10-11
    • 2018-07-17
    相关资源
    最近更新 更多