我希望有人可以帮我解决我的项目问题。我是编程的初学者,我正在学习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。请原谅我发布这么大的问题,但我想尽可能多地提供信息。
答案 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}})。