2017-10-21 422 views
0

的子節點日期時間字符串我用一個TreeView組件來實現我的HTML編輯器。 我用的子節點記錄與包括交流和公元前數據的時間串歷史事件時間。我測試過的樹形視圖的示例子節點如下所示。排序後排序子節點正確地將其包括公元和公元前在樹狀

-History 
    ﹂ 0123/05/05 B.C. event001 
    ﹂ 2015/01/01 A.D. event002 
    ﹂ 2017/01/21 A.D. event003 
    ﹂ 2125/12/05 B.C. event000 

正確的結果應該看起來像如下

-History 
    ﹂ 2125/12/05 B.C. event000 
    ﹂ 0123/05/05 B.C. event001 
    ﹂ 2015/01/01 A.D. event002 
    ﹂ 2017/01/21 A.D. event003 

我使用的代碼只是呈三角以下職位: Sorting child nodes of a treeview after populating the treeview in c# winforms

using System.Collections; 
using System.Windows.Forms; 
namespace TreeViewEditor 
{ 
    public class NodeSorter : IComparer 
    { 
     public int Compare(object x, object y) 
     { 
       TreeNode tx = x as TreeNode; 
       TreeNode ty = y as TreeNode; 
       return string.Compare(tx.Text, ty.Text); 
      } 
    } 
} 

它正常工作的子節點時內容僅限AD日期時間字符串。我想知道如何在孩子節點內容A.D.和B.C時正確排序。日期時間字符串在treeview中。要做到這一點

+1

什麼廣告/ BC日期的數據類型?一個簡短的相關代碼片段會很有幫助,顯示您當前正在使用的排序(適用於廣告) –

+1

您當前的(非工作)IComparer實現是什麼樣的? –

+3

如果我正確地閱讀,這與treeview childnodes有關,並且更多地使用適用於AD或BC日期的正確排序算法。 –

回答

1

的一種方法是使用一個類來表示您的日期,並在類實現IComparable。這使您可以自定義排序算法,以便B.C.日期按照相反的順序排列(與A.D.日期相比)。

下面我創建了一個具有年,月,日屬性的類以及爲B.C.設置爲false的bool。日期。我添加了一個Parse()方法,可以把你的例子字符串之一(不帶「事件」部分),並返回一個BCADDate對象。這將是微不足道的添加一個「事件」財產和解析字符串中的事件以及能力,如果需要的話(註釋下,我可以添加它)。

基本上比較的工作原理是:

  1. 如果日期不具有相同的BC/AD指定,那麼BC一個至上
  2. 否則,比較這些年來,然後是幾個月,然後日子,並返回第一個不匹配的比較結果。乘以它由-1
  3. 返回0如果所有屬性匹配

編輯

我加入了IComparer接口也執行,如果能夠幫助使用反向的BC日期的結果這與樹視圖。

下面的代碼:

class BCADDate : IComparable, IComparer 
{ 
    public int Year { get; set; } 
    public int Month { get; set; } 
    public int Day { get; set; } 
    public bool IsAD { get; set; } 

    public static BCADDate Parse(string input) 
    { 
     var result = new BCADDate(); 

     if (string.IsNullOrWhiteSpace(input)) 
      throw new ArgumentException("input cannot be null, empty, or whitespace"); 

     var dateADParts = input.Split(' '); 
     var dateParts = dateADParts[0].Split('/'); 

     if (dateParts.Length < 3) 
      throw new FormatException(
       "The string must have three parts separated by the '/' character."); 

     try 
     { 
      result.Year = int.Parse(dateParts[0]); 
      result.Month = int.Parse(dateParts[1]); 
      result.Day = int.Parse(dateParts[2]); 
     } 
     catch 
     { 
      throw new FormatException(
       "All parts of the date portion must be valid integers."); 
     } 

     result.IsAD = (dateADParts.Length == 1) 
      ? true // A.D. is true if nothing is specified 
      : dateADParts[1].IndexOf("A", StringComparison.OrdinalIgnoreCase) > -1; 

     return result; 
    } 

    public int CompareTo(object obj) 
    { 
     var other = obj as BCADDate; 
     if (other == null) return 1; 

     var BCMultiplier = IsAD ? 1 : -1; 

     // Use default comparers for our fields 
     if (this.IsAD != other.IsAD) 
      return this.IsAD.CompareTo(other.IsAD); 
     if (this.Year != other.Year) 
      return this.Year.CompareTo(other.Year) * BCMultiplier; 
     if (this.Month != other.Month) 
      return this.Month.CompareTo(other.Month) * BCMultiplier; 
     if (this.Day != other.Day) 
      return this.Day.CompareTo(other.Day) * BCMultiplier; 

     return 0; 
    } 

    public int Compare(object x, object y) 
    { 
     var first = x as BCADDate; 
     var second = y as BCADDate; 

     if (first == null) return second == null ? 0 : -1; 
     return first.CompareTo(second); 
    } 

    public override string ToString() 
    { 
     var bcad = IsAD ? "A.D." : "B.C."; 
     return $"{Year:0000}/{Month:00}/{Day:00} {bcad}"; 
    } 
} 

這裏的用法的示例:

var dates = new List<BCADDate> 
{ 
    BCADDate.Parse("0123/05/05 B.C."), 
    BCADDate.Parse("2015/01/01 A.D."), 
    BCADDate.Parse("2017/01/21 A.D."), 
    BCADDate.Parse("2125/12/05 B.C.") 
}; 

Console.WriteLine("Original ordering:"); 
dates.ForEach(Console.WriteLine); 

dates.Sort(); 
Console.WriteLine("------------------"); 

Console.WriteLine("Sorted ordering:"); 
dates.ForEach(Console.WriteLine); 

Console.Write("\nDone!\nPress any key to exit..."); 
Console.ReadKey(); 

輸出

enter image description here

+0

@ Rufus L感謝您的快速響應,我希望我能在某一天投票給您。:D我將在您的計劃中集成您的解決方案,並在成功時給您反饋。再次感謝你。 –

0

基於魯弗斯L的溶液,我已經實現這種排序函數在TreeView組件中。令人驚訝的是,我只是對TreeView的NodeSorter做了一些小修改。 Rufus L的解決方案在我的treeview應用程序中工作得很好。

經修改的源代碼被如下表示:在應用程序中使用的

using System; 
using System.Collections; 
using System.Windows.Forms; 
namespace TreeViewEditor 
{ 
    class BCADDate : IComparable 
    { 
     public int Year { get; set; } 
     public int Month { get; set; } 
     public int Day { get; set; } 
     public bool IsAD { get; set; } 

     public static BCADDate Parse(string input) 
     { 
      var result = new BCADDate(); 

      if (string.IsNullOrWhiteSpace(input)) 
       throw new ArgumentException("input cannot be null, empty, or whitespace"); 

      var dateADParts = input.Split(' '); 
      var dateParts = dateADParts[0].Split('/'); 

      if (dateParts.Length < 3) 
       throw new FormatException(
        "The string must have three parts separated by the '/' character."); 

      try 
      { 
       result.Year = int.Parse(dateParts[0]); 
       result.Month = int.Parse(dateParts[1]); 
       result.Day = int.Parse(dateParts[2]); 
      } 
      catch 
      { 
       throw new FormatException(
        "All parts of the date portion must be valid integers."); 
      } 

      result.IsAD = (dateADParts.Length == 1) 
       ? true // A.D. is true if nothing is specified 
       : dateADParts[1].IndexOf("A", StringComparison.OrdinalIgnoreCase) > -1; 

      return result; 
     } 

     public int CompareTo(object obj) 
     { 
      var other = obj as BCADDate; 
      if (other == null) return 1; 

      var BCMultiplier = IsAD ? 1 : -1; 

      // Use default comparers for our fields 
      if (this.IsAD != other.IsAD) 
       return this.IsAD.CompareTo(other.IsAD); 
      if (this.Year != other.Year) 
       return this.Year.CompareTo(other.Year) * BCMultiplier; 
      if (this.Month != other.Month) 
       return this.Month.CompareTo(other.Month) * BCMultiplier; 
      if (this.Day != other.Day) 
       return this.Day.CompareTo(other.Day) * BCMultiplier; 

      return 0; 
     } 
    } 

    public class NodeSorter : IComparer 
    { 
     public int Compare(object x, object y) 
     { 
      TreeNode tx = x as TreeNode; 
      TreeNode ty = y as TreeNode; 
      BCADDate a = BCADDate.Parse(tx.Text); 
      BCADDate b = BCADDate.Parse(ty.Text); 
      return a.CompareTo(b); 
     } 
    } 
} 

代碼被表示如下:

TreeView2.TreeViewNodeSorter = new NodeSorter(); 
+0

根據Rufus L的貢獻,我不會爲這篇文章改變我可以接受的答案。感謝Rufus L在決賽中。 –