2017-03-01 35 views
1

我希望有人能夠幫我解決與我的項目碰到的障礙。我初學者一般編程,我正在學習C#(WinForms)。我正在製作一個簡單的文本編輯器。我有一個豐富的文本文件和一個XML文件來存儲其他信息。在XML文件中,我有一個我想用來存儲行號的頁面節點。我有一個按鈕,可以將富文本框滾動到存儲在XML文件中的下一頁的行號。例如:使用XML節點作爲頁面列表。添加編號的XML節點,然後重新排序它們。 Visual C#

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

我有另一個按鈕,將頁面添加到頁面節點。添加新頁面時,我需要我的應用程序使用正確的名稱添加新節點,並將其放在頁面節點的正確位置。例如,爲第16行添加一個新頁面,該文件將看起來像這樣;

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

我已經得到儘可能一個添加新節點到XML文件,並獲得所選擇的行數,但我想不通的下一個步驟。 首先,我如何獲得新節點(在上面的情況下,page2)的名稱中包含正確的數字?如果您在第8行再次單擊添加頁面按鈕,它將變成第2頁,第16行變成第3頁,第32行變成第4頁等等。請參閱以下代碼中來自主form.cs文件的註釋1。

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行上的刪除頁面按鈕,則頁面3(包含第10行的節點)將被刪除,使得頁面2將從第8行到第27行。第3頁將從第28行到第第32行等。

正如我在開始時所說的,我是初學C#的人,我不知道如何做到這一點,最好的方法是什麼,或者我是否走向正確的道路。所以我希望有人能夠幫助我。我希望我已經解釋了我想要做的很清楚,並且我的問題是有道理的。

非常感謝你的時間和任何幫助。

Morgan Morgan

P.S.請原諒我發佈這樣一個巨大的問題,但我想盡可能多地提供信息。

回答

0

我認爲最好的辦法是有名爲Page的類和這些頁面的列表。然後,您可以將類序列化爲xml(並將xml反序列化爲類)。這樣你就可以操作Page集合而不用用xml來擺弄。

我會做這樣的:

[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集合。 寫入數據,並在需要時重新加載。加載後,您可以通過索引或使用foreach或使用for循環來循環訪問Pages。然後,您可以添加一個或多個頁面進行收集並重新排序。

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類增加了新的特性,以顯示其他數據如何可以添加(看看CreateData())。

+0

非常感謝你的回覆尼諾,它非常有幫助。我確實有幾個問題。首先,我得到一個FormatException'索引(基於零)必須大於或等於零,並且小於參數列表的大小。「System.Diagnostics.Debug.WriteLine(string.Format(」page number {0 },value:{1}「+(data.Pages.IndexOf(page)+ 1),page.Value));' 我google了一下,但據我所知,它的格式正確,不明白錯誤。我手動更改了xml文件,因此'page'節點與您的xml數據代碼塊相同,但它仍然會給出該FormatException。 –

+0

其次,您的代碼只用更新的'pages'節點替換'root'節點中的所有內容,並刪除我的應用程序需要啓動的所有其他數據。因此,如何在不刪除或以其他方式影響xml文件中的任何其他節點的情況下重寫「pages」節點? 再次感謝您的時間和幫助 摩根 –

+0

我編輯了代碼並修正了'string.Format'錯誤。應該用逗號代替加號,就像這樣System.Diagnostics.Debug.WriteLine(string.Format(「page number {0},value:{1}」,(data.Pages.IndexOf(page)+ 1) ,page.Value))'。如果對你來說更容易一些,那麼在你的輸出窗口中寫入數據的同一行(使用'View - > Output'打開它,然後從下拉列表中選擇'Debug')可以這樣寫:System.Diagnostics.Debug.WriteLine (「page number」+(data.Pages.IndexOf(page)+ 1).ToString()+「,value:」+ page.Value.ToString());'。 – Nino