Sorting child nodes of a treeview after populating the treeview in c# winforms

前端 未结 4 1308
谎友^
谎友^ 2020-12-11 20:36

I am having trouble sorting child nodes of a treeview in my winforms program. My treeview is populated by some XML files and it uses an internal text inside the xml files as

相关标签:
4条回答
  • 2020-12-11 21:09

    I've written some custom comparers to make creating the comparer you need here somewhat easier to do: MultiComparer and ProjectionComparer. Together, you could create a comparer to sort what you need on the fly without having to create a class by hand. What I provide here isn't actually how I have the classes written, I trimmed off a lot of code for brevity (though left some helpers to be easier to use).

    To create the comparer:

    var comparer = OrderedComparer.Create(
        ProjectionComparer.Create((TreeNode tn) => tn.Text.Substring(0, 1)),
        ProjectionComparer.Create((TreeNode tn) => Convert.ToInt32(tn.Text.Substring(1)))
    );
    treeView.TreeViewNodeSorter = comparer;
    

    And the classes:

    public static class OrderedComparer
    {
        public static OrderedComparer<TSource> Create<TSource>(params IComparer<TSource>[] comparers)
        { return new OrderedComparer<TSource>(comparers); }
    }
    public static class ProjectionComparer
    {
        public static ProjectionComparer<TSource, TKey> Create<TSource, TKey>(Func<TSource, TKey> keySelector)
        { return new ProjectionComparer<TSource, TKey>(keySelector); }
    }
    public sealed class OrderedComparer<TSource> : Comparer<TSource>
    {
        public OrderedComparer(params IComparer<TSource>[] comparers)
        {
            this.comparers = comparers.ToArray();
        }
        private IComparer<TSource>[] comparers;
    
        public override int Compare(TSource x, TSource y)
        {
            var cmp = 0;
            foreach (var comparer in comparers)
                if ((cmp = comparer.Compare(x, y)) != 0)
                    break;
            return cmp;
        }
    }
    public sealed class ProjectionComparer<TSource, TKey> : Comparer<TSource>
    {
        public ProjectionComparer(Func<TSource, TKey> keySelector)
        {
            this.keySelector = keySelector;
            this.keyComparer = Comparer<TKey>.Default;
        }
        private Func<TSource, TKey> keySelector;
        private IComparer<TKey> keyComparer;
    
        public override int Compare(TSource x, TSource y)
        {
            var xKey = keySelector(x);
            var yKey = keySelector(y);
            return keyComparer.Compare(xKey, yKey);
        }
    }
    
    0 讨论(0)
  • 2020-12-11 21:11

    You're using alphabetic sorting, so D10 comes after D1.
    You should try to sort discarding "D" char and converting the rest of string to a number.

    0 讨论(0)
  • 2020-12-11 21:13

    Following is the solution I have used in my current project.

    public class NodeSorter : IComparer
    {
       public int Compare(object x, object y)
       {
          TreeNode tx = x as TreeNode;
          TreeNode ty = y as TreeNode;
          if (tx.Name== null || ty.Name== null)
             return 0;
          return (-1) * string.Compare(tx.Name.ToString(), ty.Name.ToString());
       }
    } 
    
    tvListofItems.TreeViewNodeSorter = new NodeSorter();
    tvListofItems.Sort();              
    
    0 讨论(0)
  • 2020-12-11 21:22

    You need to create a custom comparer and assign it to the TreeViewNodeSorter property:

    public class NodeSorter : System.Collections.IComparer
    {
        public int Compare(object x, object y)
        {
            TreeNode tx = (TreeNode)x;
            TreeNode ty = (TreeNode)y;
    
            // Your sorting logic here... return -1 if tx < ty, 1 if tx > ty, 0 otherwise
            ...
        }
    }
    
    
    ...
    
    treeView.TreeViewNodeSorter = new NodeSorter();
    treeView.Sort();
    
    0 讨论(0)
提交回复
热议问题