使用XML节点作为页面列表。添加编号的XML节点,然后重新排序。 Visual C#

时间:2017-03-01 10:47:24

标签: c# xml winforms line

我希望有人可以帮我解决我的项目问题。我是编程的初学者,我正在学习C#(WinForms)。我正在制作一个简单的文本编辑器。我有一个富文本文件和一个XML文件来存储其他信息。在XML文件中,我有一个页面节点,我想用它来存储行号。我有一个按钮,可以将富文本框滚动到存储在XML文件中的下一页的行号。例如:

<pages>
  <page1>0</page1>
  <page2>32</page2>
</pages>

我有另一个按钮,它将页面添加到页面节点。添加新页面时,我需要我的应用程序添加具有正确名称的新节点,并在页面节点中的正确位置。例如,为第16行添加新页面,文件将如下所示;

<pages>
  <page1>0</page1>
  <page2>16</page2>
  <page3>32</page3>
</pages>

到目前为止,我已经在XML文件中添加了一个新节点并获取了所选的行号,但我无法弄清楚下一步。 首先,如何让新节点(在上面的情况下,第2页)在其名称中包含正确的数字?如果你在第8行再次点击添加页面按钮,它将成为page2,第16行将成为page3,第32行将成为page4,依此类推。请参阅以下代码中的注释1,该代码来自主form.cs文件。

string xmlFile = @"C:/test.xml";

private void bottomBarAddPageButton_Click(object sender, EventArgs e)
    {
        int cursorPosition = mainTextbox.SelectionStart;
        int lineIndex = mainTextbox.GetLineFromCharIndex(cursorPosition);
        XmlNode pagesNodes = XmlReader.SelectSingleNode("root/pages");
        XmlNode pageNodeCreate = XmlReader.CreateElement("page"); // Comment 1: Needs to add correct page number here 
        pageNodeCreate.InnerText = Convert.ToString(lineIndex);
        pagesNodes.AppendChild(pageNodeCreate);
        XmlReader.Save(xmlFile);
    }

以下是XML文件目前的样子。单击bottomBarAddPageButton会添加一个名为page的新节点,并将内部文本作为选定的行号(lineIndex)。

<root>
  <otherNodes>
  <pages>
    <page>0</page>
    <page>28</page>
    <page>32</page>
    <page>8</page>
    <page>76</page>
    <page>10</page>
  </pages>
</root>

其次,添加新节点后,如何重新排序页面中的所有子节点,以便XML文件看起来像这样?

<root>
  <otherNodes>
  <pages>
    <page1>0</page1>
    <page2>8</page2>
    <page3>10</page3>
    <page4>28</page4>
    <page5>32</page5> 
    <page6>76</page6>       
  </pages>
</root>

我还需要能够在删除页面时执行相反的操作。例如,如果单击富文本框第19行上的删除页面按钮,则将删除page3(包含第10行的节点),以便page2将从第8行到第27行.page3将从第28行到第23行。第32行等等。

正如我在开始时说的那样,我是初学C#并且我不知道如何做到这一点,最好的方法是什么,或者我是否走上了正确的道路。所以我希望那里的人能够帮助我。我希望我已经解释了我要做的事情,并且我的问题是有道理的。

非常感谢你的时间和任何帮助。

摩根

P.S。请原谅我发布这么大的问题,但我想尽可能多地提供信息。

1 个答案:

答案 0 :(得分:0)

我认为最好的方法是将类命名为Page并列出这些页面。然后,您可以将类序列化为xml(并再次将xml反序列化为类)。这样你就可以在不摆弄xml的情况下操纵Page集合。

我会这样做:

<强>类

[Serializable]
[XmlRoot("root")]
public class Data
{

    [XmlArray("Pages")]
    [XmlArrayItem(ElementName = "Page", Type = typeof(Page))]
    public List<Page> Pages { get; set; }

    //add as many properties as needed
    public int SomeIntNode { get ; set; }

    //using [XmlElement] attribute, you can change how the element will be named in xml 
    [XmlElement("otherName")]
    public string Name { get; set; }

}

[Serializable]
public class Page
{
    [XmlAttribute]
    public int Value { get; set; }

    //you can add additional attributes if needed.
    //just make a property and add [XmlAttribute] attrib, like this:
    //[XmlAttribute]
    //public sting SomeText { get; set; }
    //so it will be written as <Page Value="123" SomeText="abc" />
}

Data只是包含Pages集合的容器。如果您还希望序列化,可以向Data类添加其他属性。

Page是包含值的类(RichTextBox中的行)。

[XmlArray("Pages")][XmlArrayItem(ElementName = "Page", Type = typeof(Page))]等属性用作序列化程序的附加说明(将数据转换为xml格式的类)。首先告诉序列化器如何命名集合,然后告诉如何命名元素及其类型。 属性[Serializable]表示该类可以序列化。

<强>用法

创建Data类的实例,并将页面添加到其Pages集合中。 写入数据,并在必要时再次加载。加载后,您可以通过索引或使用Pages或使用foreach循环来遍历for。然后,您可以将一个或多个页面添加到集合中并再次对其进行排序。

public void Test()
{ 

    //create data and write it to xml
    CreateData();
    //load data from xml
    Data data = LoadData();
    //iterate thru collection if needed
    foreach (Page page in data.Pages)
    {
        System.Diagnostics.Debug.WriteLine(string.Format("page number {0}, value: {1}",(data.Pages.IndexOf(page) + 1), page.Value));
        //or, you can write to debug window like this:
        //System.Diagnostics.Debug.WriteLine("page number " + (data.Pages.IndexOf(page) + 1).ToString() + ", value: " + page.Value.ToString());
        //or fill some listbox
        //listBox1.Items.Add("page number " + (data.Pages.IndexOf(page) + 1).ToString() + ", value: " + page.Value.ToString());
        //...
    }
    //access second page (by index... index 1 is page 2)
    var specificPage = data.Pages[1];
    //add additional page and sort it by value
    data.Pages.Add(new Page() { Value = 15 });
    data.Pages.OrderBy(x => x.Value);
    //write again if needed
    WriteToXml(data);

}

private void CreateData()
{
    Data data = new Data();
    data.Pages = new List<Page>();             
    data.Pages.Add(new Page() { Value = 10 });
    data.Pages.Add(new Page() { Value = 20 });
    data.Pages.Add(new Page() { Value = 30 });

    //other properties
    data.SomeIntNode = 100;
    data.Name = "here is name";

    WriteToXml(data);

}

private void WriteToXml(Data data)
{
    XmlSerializer xSer = new XmlSerializer(typeof(Data));
    using (TextWriter writer = new StreamWriter(@"c:\temp\pages.xml"))
    {
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add("", "");
        xSer.Serialize(writer, data, ns);
    }
}

private Data LoadData()
{
    XmlSerializer xSer = new XmlSerializer(typeof(Data));
    using (TextReader reader = new StreamReader(@"c:\temp\pages.xml"))
    {
        return xSer.Deserialize(reader) as Data;
    }
}

xml数据(编辑:因新属性和新根名称而更新)

<?xml version="1.0" encoding="utf-8"?>
<root>
  <Pages>
    <Page Value="10" />
    <Page Value="20" />
    <Page Value="30" />
    <Page Value="15" />
  </Pages>
  <SomeIntNode>1000</SomeIntNode>
  <otherName>here is name</otherName>
</root>

如果您有任何问题,请随时提出。

编辑:将data元素重命名为root(更像您的样本),并在Data类中添加新属性,以显示如何添加其他数据(查看{{ 1}})。