0

i am using treeView to show sequence directory and its subdirectory and files in the treeView on form and i use the following method to load the tree view

in form load :

        treeView1.Nodes.Clear();
        toolTip1.ShowAlways = true;
        LoadDirectory("C:\\Windows\\System32\\" + inventedName );  

and the following 3 methods to load directory and subdirectory and files

    public void LoadDirectory(string Dir)
    {

        DirectoryInfo di = new DirectoryInfo(Dir);

        TreeNode tds = treeView1.Nodes.Add(di.Name);

        tds.Tag = di.FullName;
        //tds.StateImageIndex = 0;
        tds.ImageIndex = 0;
        tds.StateImageIndex = 0;
        tds.SelectedImageIndex = 0;
        LoadFiles(Dir, tds);
        LoadSubDirectories(Dir, tds);
    }

    private void LoadSubDirectories(string dir, TreeNode td)
    {

        string[] subdirectoryEntries = Directory.GetDirectories(dir);          

        // Loop through them to see if they have any other subdirectories  
        foreach (string subdirectory in subdirectoryEntries)
        {

            DirectoryInfo di = new DirectoryInfo(subdirectory);
            TreeNode tds = td.Nodes.Add(di.Name);
            renameNodes(tds);    
            //tds.StateImageIndex = 0;
            tds.Tag = di.FullName;
            tds.ImageIndex = 0;
            tds.StateImageIndex = 0;
            tds.SelectedImageIndex = 0;
            LoadFiles(subdirectory, tds);
            LoadSubDirectories(subdirectory, tds);

        }
    }

    private void LoadFiles(string dir, TreeNode td)
    {
        string[] Files = Directory.GetFiles(dir, "*.pdf");

        // Loop through them to see files  
        foreach (string file in Files)
        {
            FileInfo fi = new FileInfo(file);
            TreeNode tds = td.Nodes.Add(fi.Name);
            tds.Tag = fi.FullName;
            tds.ImageIndex = 1;
            tds.StateImageIndex = 1;
            tds.SelectedImageIndex = 1;

        }
    }

my problem is the subdirectories (folder) have specific names i can not change it for example :

> root 
    > parent 
          > 1.0 xxx
          > 1.10 xxx
          > 1.2 xxx
          > 1.3 xxx 
          > 1.4 xxx
          > 1.5 xxx
          > 1.6 xxx
          > 1.7 xxx
          > 1.8 xxx
          > 1.9 xxx

but i need it to be like that

> root 
    > parent 
         > 1.0 xxx
         > 1.2 xxx
         > 1.3 xxx 
         > 1.4 xxx
         > 1.5 xxx
         > 1.6 xxx
         > 1.7 xxx
         > 1.8 xxx
         > 1.9 xxx
         > 1.10 xxx 

the stupid (1.10 xxx) child must be after (1.9 xxx) child and as i told i can not rename the folder that will be wrong is there is any way to send it to be the last child

thanks for helping me

  • Possible duplicate of [Sorting child nodes of a treeview after populating the treeview in c# winforms](https://stackoverflow.com/questions/5618506/sorting-child-nodes-of-a-treeview-after-populating-the-treeview-in-c-sharp-winfo) – vik_78 Apr 19 '19 at 15:50
  • You should sort the list of files. [In this post](https://stackoverflow.com/questions/1548312/sorting-a-listview-by-column/44469258?r=SearchResults&s=1|53.9582#44469258) you can find a function in the update section that expands strings to sortable numbers.. – TaW Apr 19 '19 at 15:58
  • Dear @vik_78 i tried it but it don't work for me – Mohamed Magdy Elsayed Apr 19 '19 at 17:02
  • Dear @TaW thanks for your comment but i am using treeView that method works with list View – Mohamed Magdy Elsayed Apr 19 '19 at 17:04
  • I know. The code could teach you what to do. And, as I wrote, this is not about a TreeView really but about gettting a suitably sorted list from which you create the nodes.. – TaW Apr 19 '19 at 17:17

2 Answers2

0

I did a very similar solution a few weeks ago using IEquable. I sorted the filenames in code below to get correct solution

   public class Test
    {
        private void LoadFiles(string dir, TreeNode td)
        {
            string[] Files = Directory.GetFiles(dir, "*.pdf");
            Files = Files.Select(x => new MySort(x)).OrderBy(x => x).Select(x => x.filename).ToArray();

            // Loop through them to see files  
            foreach (string file in Files)
            {
                FileInfo fi = new FileInfo(file);
                TreeNode tds = td.Nodes.Add(fi.Name);
                tds.Tag = fi.FullName;
                tds.ImageIndex = 1;
                tds.StateImageIndex = 1;
                tds.SelectedImageIndex = 1;

            }
        }
    }
    public class MySort : IComparable
    {
        private string[] splitvalues { get; set; }
        public string filename { get; set; }

        public MySort(string filename)
        {
            this.filename = filename;
            splitvalues = filename.Split(new char[] { '.', ' ' }, StringSplitOptions.RemoveEmptyEntries).ToArray();

        }
        public int CompareTo(object other)
        {
            MySort otherMySort = (MySort)other;
            int min = Math.Min(this.splitvalues.Length, otherMySort.splitvalues.Length);

            for (int i = 0; i < min; i++)
            {
                string a = this.splitvalues[i];
                string b = otherMySort.splitvalues[i];

                if (a != b)
                {

                    int numberA = 0;
                    int numberB = 0;

                    if (int.TryParse(a, out numberA))
                    {
                        if (int.TryParse(b, out numberB))
                        {
                            int z = numberA.CompareTo(numberB);
                            //a & b are numbers
                            return numberA.CompareTo(numberB);
                        }
                        else
                        {
                            //a number b string
                            return -1;
                        }

                    }
                    else
                    {
                        if (int.TryParse(b, out numberB))
                        {
                            //a string b number
                            return 1;
                        }
                        else
                        {
                            // a string b string
                            return a.CompareTo(b);
                        }
                    }
                }
            }
            return splitvalues.Length.CompareTo(otherMySort.splitvalues.Length);

        }
    }
jdweng
  • 33,250
  • 2
  • 15
  • 20
  • dear @jdweng thanks for your help i tried your method and thats whats happens before using it https://ibb.co/dBhDqYD and that what happens after using the method – Mohamed Magdy Elsayed Apr 19 '19 at 17:45
  • dear @jdweng thanks for your help i tried your method and thats whats happens before using it https://ibb.co/dBhDqYD and that what happens after using the method https://ibb.co/0r9ZdJN but i need it to be after 1.9 node any solution – Mohamed Magdy Elsayed Apr 19 '19 at 17:51
0

The code works properly as you can see from test code below. I made one small change to add a Sort() method to make it easier to call the code. Everything else is the same. :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] input = { "1.7.1", "1.7.10", "1.7.2", "1.7.3", "1.7.4", "1.7.5", "1.7.6", "1.7.7", "1.7.8", "1.7.9" };
            string[] output = MySort.Sort(input);
        }
    }
    public class MySort : IComparable
    {
        private string[] splitvalues { get; set; }
        public string filename { get; set; }

        public MySort(string filename)
        {
            this.filename = filename;
            splitvalues = filename.Split(new char[] { '.', ' ' }, StringSplitOptions.RemoveEmptyEntries).ToArray();

        }
        public static string[] Sort(string[] input)
        {
            return input.Select(x => new MySort(x)).OrderBy(x => x).Select(x => x.filename).ToArray();
        }
        public int CompareTo(object other)
        {
            MySort otherMySort = (MySort)other;
            int min = Math.Min(this.splitvalues.Length, otherMySort.splitvalues.Length);

            for (int i = 0; i < min; i++)
            {
                string a = this.splitvalues[i];
                string b = otherMySort.splitvalues[i];

                if (a != b)
                {

                    int numberA = 0;
                    int numberB = 0;

                    if (int.TryParse(a, out numberA))
                    {
                        if (int.TryParse(b, out numberB))
                        {
                            int z = numberA.CompareTo(numberB);
                            //a & b are numbers
                            return numberA.CompareTo(numberB);
                        }
                        else
                        {
                            //a number b string
                            return -1;
                        }

                    }
                    else
                    {
                        if (int.TryParse(b, out numberB))
                        {
                            //a string b number
                            return 1;
                        }
                        else
                        {
                            // a string b string
                            return a.CompareTo(b);
                        }
                    }
                }
            }
            return splitvalues.Length.CompareTo(otherMySort.splitvalues.Length);

        }
    }
}
jdweng
  • 33,250
  • 2
  • 15
  • 20
  • The code splits the number on the period character. If the filenames are using a different character than a period the code will not sort correctly. – jdweng Apr 20 '19 at 11:21