排序子节点正确地将其包括公元和公元前在树状

排序子节点正确地将其包括公元和公元前在树状

问题描述:

的子节点日期时间字符串我用一个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日期的正确排序算法。 –

的一种方法是使用一个类来表示您的日期,并在类实现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我将在您的计划中集成您的解决方案,并在成功时给您反馈。再次感谢你。 –

基于鲁弗斯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在决赛中。 –