排序子节点正确地将其包括公元和公元前在树状
的子节点日期时间字符串我用一个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中。要做到这一点
的一种方法是使用一个类来表示您的日期,并在类实现IComparable
。这使您可以自定义排序算法,以便B.C.日期按照相反的顺序排列(与A.D.日期相比)。
下面我创建了一个具有年,月,日属性的类以及为B.C.设置为false
的bool。日期。我添加了一个Parse()
方法,可以把你的例子字符串之一(不带“事件”部分),并返回一个BCADDate
对象。这将是微不足道的添加一个“事件”财产和解析字符串中的事件以及能力,如果需要的话(注释下,我可以添加它)。
基本上比较的工作原理是:
- 如果日期不具有相同的BC/AD指定,那么BC一个至上
- 否则,比较这些年来,然后是几个月,然后日子,并返回第一个不匹配的比较结果。乘以它由
-1
- 返回
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();
输出
@ 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();
根据Rufus L的贡献,我不会为这篇文章改变我可以接受的答案。感谢Rufus L在决赛中。 –
什么广告/ BC日期的数据类型?一个简短的相关代码片段会很有帮助,显示您当前正在使用的排序(适用于广告) –
您当前的(非工作)IComparer实现是什么样的? –
如果我正确地阅读,这与treeview childnodes有关,并且更多地使用适用于AD或BC日期的正确排序算法。 –