如何使SortDescription按不同的方式排序字符串

8
我有以下字符串:
"String 1"
"String 2"
"String 3"
"String 15"
"String 17"
我希望按照上面的顺序对这些字符串进行排序。但是,当我使用SortDescription来对我的列表进行排序时,输出如下:
"String 1"
"String 15"
"String 17"
"String 2"
"String 3"
我知道有算法可以完成这个任务,但是是否有一种方法可以利用SortDescription的内置功能来实现呢?
private void SortCol(string sortBy, ListSortDirection direction)
{
        ICollectionView dataView =
          CollectionViewSource.GetDefaultView(ListView.ItemsSource);

        dataView.SortDescriptions.Clear();

        SortDescription sd = new SortDescription(sortBy, direction);
        dataView.SortDescriptions.Add(sd);
        dataView.Refresh();
}

sortby是我视图模型中表示我想要排序的列的属性名称。

似乎我的唯一两个排序选项是升序和降序。但它对CollectionView进行排序的方式并不是我希望字符串排序的方式。有没有简单的方法来解决这个问题?


请给我们展示一些代码以供参考。 - Simon Whitehead
http://www.codinghorror.com/blog/2007/12/sorting-for-humans-natural-sort-order.html - I4V
谢谢您的评论,但我不知道如何在ListView中实现。这是我想在ListView中实现的相似功能: http://stackoverflow.com/questions/10582996/how-to-sort-by-integer-in-a-listitemcollection-in-wpf - jsirr13
1
@jsirr13,我认为你走在了正确的道路上! - failedprogramming
5
将这个标记为重复是错误的。问题的背景完全不同。当然,任何人都可以使用任何语言编写算法来进行排序,但这与xaml和视图绑定到视图模型属性有关。 - shawn1874
2
@shawn1874同意 - 这个答案特别帮助我发现了CollectionView上的“CustomSort”属性,这是我之前忽略了的。我在一个通用的排序算法问题中不会学到这个。 - Xcalibur
2个回答

8
通过这个链接找到了答案:C#自然排序
[SuppressUnmanagedCodeSecurity]
internal static class SafeNativeMethods
{
    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
    public static extern int StrCmpLogicalW(string psz1, string psz2);
}

public sealed class NaturalStringComparer : IComparer<string>
{
    public int Compare(object a, object b)
    {
        var lhs = (MultiItem)a;
        var rhs = (MultiItem)b;
        //APPLY ALGORITHM LOGIC HERE
        return SafeNativeMethods.StrCmpLogicalW(lhs.SiteName, rhs.SiteName);
    }
}

以下是我如何使用上述算法比较器:

    private void SortCol()
    {
        var dataView =
                      (ListCollectionView)CollectionViewSource.GetDefaultView(ListViewMultiSites.ItemsSource);
        dataView.CustomSort = new NaturalOrderComparer();
        dataView.Refresh();
    }

如果您不想使用dll导入,编写自己的比较器很容易。请参考此链接获取代码。http://www.dotnetperls.com/alphanumeric-sorting - failedprogramming
使用dll导入的缺点是什么,只是好奇? - jsirr13
我认为在使用dll导入时可能需要考虑一些问题,例如处理非托管资源、文件大小的轻微增加以及无法访问源代码。然而,我不认为我有足够的知识来给你一个好的答案。对于这个特定的dll,如果你仔细阅读链接,你会发现其功能会因操作系统而异。你需要决定这是否对你造成了问题。 - failedprogramming
如果您喜欢托管解决方案(无本机代码),您可以使用我的NaturalSort类。它还添加了更多功能以自定义顺序。 - ygoe
另一个问题是:这仅适用于单个列。除非您放弃其灵活性并在自定义比较器中硬编码多列排序,否则无法替代使用多个SortDescriptions。即使只有一列,如果用户可以通过单击列标题进行排序,它也不能使用。 - ygoe
2
使用这个方法非常好,但是NaturalStringComparer必须实现IComparer而不是泛型版本。 - Maxence

2
你可以使用 Linq。
var list = new List<string>
{
   "String 1",
   "String 17",
   "String 2",
   "String 15",
   "String 3gg"
};

var sort = list.OrderBy(s => int.Parse(new string(s.SkipWhile(c => !char.IsNumber(c)).TakeWhile(c => char.IsNumber(c)).ToArray())));

返回:

   "String 1",
   "String 2",
   "String 3gg"
   "String 15",
   "String 17",

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接