• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 770
  • Last Modified:

How to sort a treeview alfabeticly

Hi,

On my form I have a treeview on the left and a textbox on the right devided with a splitter.
The treeview nodes are loaded and saved to/from a database. It all works fine.
But the only thing the treeview doesn't do is to sort its nodes alphabeticly.

I have searched and searched but couldn't find the problem on my own.  So i don't know if the
code is allready there to sort the nodes alfabeticly. What I do know is that if its there
it doesn't work. Who can help me with this example.

Peter
namespace DbTreeView
{
    public partial class MainForm : Form
    {
        private ContextMenu tvSampleMenu = new ContextMenu();
        private const string ImageIndexColumnName = "ImageIndex";
        private const string SelectedImageIndexColumnName = "SelectedImageIndex";
        private const string SortOrderColumnName = "SortOrder";
        private string DBName = "";
        private string DBConStr = "";

        public MainForm()
        {
            InitializeComponent();
        }
        //*----------------------------------------------------------*//
        private void MainForm_Load(object sender, EventArgs e)
        {
            Hourglass(true);
            try
         {
        DBName = Application.StartupPath + @"\DBRoot.mdb";
        DBConStr = @"Provider=Microsoft.Jet.OLEDB.4.0;Password="""";Data Source=" + DBName +";";
        tvSampleMenu.MenuItems.Add("Add Folder", new EventHandler(tvSampleRightClickInsFolder));
        LoadTree(tvNotes, GetHierarchy(DBConStr, 1));
         }
         catch (Exception err) { Hourglass(false); MessageBox.Show(err.Message); }
         finally { Hourglass(false); }
        }
        //*----------------------------------------------------------*//
        private void LoadTree(TreeView tv, DataSet ds)
        {
            Hourglass(true);
            try
            {
                LoadFromDataSet(tv, ds, "Description");
                if (tv.Nodes.Count > 0)
                {
                    tv.Nodes[0].Expand();
                }
            }
            catch (Exception) { throw; }
            finally { Hourglass(false); }
        }
        //*----------------------------------------------------------*//
        public static DataSet GetHierarchy(string connectionString, int modelID)
        {
            string sql = "";
            DataSet ds = null;
            try
            {
                sql = "select * from hierarchy ";
                sql += "  where modelid=" + modelID.ToString();
                sql += "  order by parentnodeid,sortorder asc";
                ds = GetDataSet(connectionString, sql);
                SetHierarchyRelationships(ds);
            }
            catch (Exception) { throw; }
            return ds;
        }
        //*----------------------------------------------------------*//
        public static void SetHierarchyRelationships(DataSet ds)
        {
            DataColumn fk;
            DataColumn[] pk = new DataColumn[1];
            ForeignKeyConstraint fkcdelete;
            DataRelation relation;
            string datarelationname = "ParentChild";
            try
            {
                ds.Tables[0].TableName = "Hierarchy";
                pk[0] = ds.Tables[0].Columns["NodeID"];
                fk = ds.Tables[0].Columns["ParentNodeID"];
                ds.Tables[0].PrimaryKey = pk;
                fkcdelete = new ForeignKeyConstraint(pk[0], fk);
                fkcdelete.DeleteRule = Rule.Cascade;
                relation = new DataRelation(datarelationname, pk[0], fk, false);
                ds.Tables[0].Constraints.Add(fkcdelete);
                ds.Tables[0].AcceptChanges();
                ds.Relations.Add(relation);
            }
            catch (Exception) { throw; }
            return;
        }
        //*----------------------------------------------------------*//
        public static bool CommitHierarchy(string connectionString, DataSet ds)
        {
            string sql = "";
            bool ret = false;
            int ModelID = 0;
            DataTable dt;
            try
            {
                if (ds.Tables.Count < 1) { return ret; }
                dt = ds.Tables[0];
                ModelID = int.Parse(dt.Rows[0]["ModelID"].ToString());
                sql = "select  * from Hierarchy where ModelID = " + ModelID.ToString();
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    if (dt.Rows[i].RowState.ToString() == "Deleted") { continue; }
                    if (int.Parse(dt.Rows[i]["ModelID"].ToString()) != ModelID)
                    {
                        dt.Rows[i]["ModelID"] = ModelID;
                    }
                }
                CommitToDataBase(connectionString, ds, sql);
                ret = true;
            }
            catch (Exception e)
            {
                //Debug.WriteLine(e.Message);
                throw;
            }
            return ret;
        }
        //*----------------------------------------------------------*//
        public static void CommitToDataBase(string connectionString, DataSet ds, string sql)
        {
            try
            {
                if (!ds.HasChanges()) { return; }
                using (OleDbConnection conn = new OleDbConnection())
                {
                    conn.ConnectionString = connectionString;
                    conn.Open();
                    using (OleDbDataAdapter da = new OleDbDataAdapter(sql, conn))
                    {
                        OleDbCommandBuilder b = new OleDbCommandBuilder(da);
                        da.Update(ds.Tables[0]);
                        ds.AcceptChanges();
                    }
                }
            }
            catch (Exception) { throw; }
        }
        //*----------------------------------------------------------*//
        public static DataSet GetDataSet(string connectionString, string sql)
        {
            DataSet ds = new DataSet();
            try
            {
                using (OleDbConnection conn = new OleDbConnection())
                {
                    conn.ConnectionString = connectionString;
                    conn.Open();
                    using (OleDbDataAdapter da = new OleDbDataAdapter(sql, conn))
                    {
                        da.Fill(ds);
                    }
                }
            }
            catch (Exception) { throw; }
            return ds;
        }        
        //*----------------------------------------------------------*//
        private void InsertNewFolder(TreeNode node)
        {
         DataRow row = null;
         DataRow ParentRow = null;
         DataTable dt = null;
         int newindex = 0;
         try
         {
             ParentRow = (DataRow)node.Tag; 
             if (ParentRow == null) { return; }
             newindex = int.Parse(ParentRow["SortOrder"].ToString()) + 1;
             dt = ParentRow.Table;
             row = dt.NewRow();
             row["ModelID"] = int.Parse(ParentRow["ModelID"].ToString());
			 row["NodeID"] = Guid.NewGuid().ToString();
			 row["ParentNodeID"] = ParentRow[dt.PrimaryKey[0].ColumnName].ToString();
             row["Description"] = "New Node";
			 row["ImageIndex"] = 1;
			 row["SelectedImageIndex"] = 2;
             row["SortOrder"] = newindex;
             row["Data"] = txtbNotes.Text;
             dt.Rows.Add(row);
             TreeNode newNode = GetTreeNodeFromDataRow(row, "Description");
             node.Nodes.Add(newNode);
             tvNotes.SelectedNode = newNode; 
         }
         catch (Exception) { throw; }
        }
        //*----------------------------------------------------------*//
        private void tvSampleRightClickInsFolder(object sender, System.EventArgs e)
        {
            Hourglass(true);
            try
            {
                TreeNode node = tvNotes.SelectedNode;
                if ((node == null) || (node.ImageIndex == 3)) { return; }
                InsertNewFolder(node);
            }
            catch (Exception err) { MessageBox.Show(err.Message); }
            finally { Hourglass(false); }
        }
        //*----------------------------------------------------------*//
        public static void LoadFromDataSet(TreeView tv, DataSet ds, string textColumnName)
        {
            TreeNode node;
            DataRow row;
            try
            {
                tv.Nodes.Clear();
                if (ds.Tables.Count < 1) { return; }
                if (ds.Tables[0].Rows.Count < 1) { return; }
                string fkcolumnname = FindForeignKeyColumnName(ds.Tables[0]);
                row = ds.Tables[0].Rows[0];
                tv.BeginUpdate();
                node = GetTreeNodeFromDataRow(row, textColumnName);
                tv.Nodes.Add(node);
                AddNodeFromDataRow(node, row, textColumnName, FindForeignKeyRelationName(row.Table));
            }
            catch (Exception) { throw; }
            finally
            {
                tv.EndUpdate();
                ds.AcceptChanges();
            }
        }
        //*----------------------------------------------------------*//
        public static void AddNodeFromDataRow(TreeNode parentNode, DataRow row, string textColumnName, string dataRelationName)
        {
            try
            {
                foreach (DataRow childrow in row.GetChildRows(dataRelationName))
                {
                    parentNode.Nodes.Add(GetTreeNodeFromDataRow(childrow, textColumnName));
                    AddNodeFromDataRow(parentNode.LastNode, childrow, textColumnName, dataRelationName);
                }
            }
            catch (Exception) { throw; }
        }
        //*----------------------------------------------------------*//
        public static TreeNode GetTreeNodeFromDataRow(DataRow row, string textColumnName)
        {
            TreeNode child = null;
            string imageidx = "";
            string selimageidx = "";
            try
            {
                if (row.Table.Columns.Contains(ImageIndexColumnName))
                {
                    imageidx = row[ImageIndexColumnName].ToString();
                }
                if (row.Table.Columns.Contains(SelectedImageIndexColumnName))
                {
                    selimageidx = row[SelectedImageIndexColumnName].ToString();
                }
                child = new TreeNode();
                child.Text = row[textColumnName].ToString().Trim();
                if (imageidx.Length > 0)
                {
                    child.ImageIndex = Convert.ToInt32(imageidx);
                }
                if (selimageidx.Length > 0)
                {
                    child.SelectedImageIndex = Convert.ToInt32(selimageidx);
                }
                child.Tag = row;
            }
            catch (Exception) { throw; }
            return child;
        }
        //*----------------------------------------------------------*//
        public static string FindForeignKeyColumnName(DataTable dt)
        {
            string Ret = "";
            try
            {
                DataSet ds = dt.DataSet;
                DataRelation rel = ds.Relations[0];
                Ret = rel.ChildColumns[0].ColumnName;
            }
            catch (Exception) { throw; }
            return Ret;
        }
        //*----------------------------------------------------------*//
        public static string FindForeignKeyRelationName(DataTable dt)
        {
            string Ret = "";
            try
            {
                DataSet ds = dt.DataSet;
                DataRelation rel = ds.Relations[0];
                Ret = rel.RelationName;
            }
            catch (Exception) { throw; }
            return Ret;
        }
        //*----------------------------------------------------------*//
	}
}

Open in new window

0
peterkiers
Asked:
peterkiers
  • 5
  • 4
2 Solutions
 
crysallusCommented:
I've done this before by assigning to the TreeView's TreeViewNodeSorter property a class that implements IComparer, which defines the basis for sorting in a Compare method. To just do basic alphabetic sorting on the Text property of the TreeNode, this should work:

public class TreeViewSorter : IComparer
{
	public int Compare(object x, object y)
	{
		var n1 = x as TreeNode;
		var n2 = y as TreeNode;

		if (n1 == null || n2 == null)
			return 0;

		return string.Compare(n1.Text, n2.Text);
	}
}

Open in new window

Then add this line to assign it to the treeview, probably in the constructor for your form, or perhaps your form's load event.

tvNotes.TreeViewNodeSorter = new TreeViewSorter();

Open in new window

You may want to change the name to something less generic, but that at least gives you the idea.

You can also implement more complicated sorting criteria, just return -1 if x comes before y, 1 if x comes after y.
0
 
satishmpCommented:
HI ,

the easiest way to sort a TreeView is to:

* add the nodes to an ArrayList
* sort the ArrayList with an IComparer
* remove the nodes from the TreeView and add them back from the
ArrayList.

e.g. in a sub-class of TreeView:

public void Sort(IComparer comparer) {

ArrayList list = new ArrayList(this.Nodes.Count);
foreach (TreeNode childNode in this.Nodes) {
list.Add(childNode);
}
list.Sort(comparer);

this.BeginUpdate();
this.Nodes.Clear();
foreach (TreeNode childNode in list) {
this.Nodes.Add(childNode);
}
this.EndUpdate();
}

Obviously, this can be adapted to deal with the child-nodes of
individual nodes. Just pass a node to the method above, and replace
this.Nodes with node.Nodes.

You can also do it with API calls, but it's messy and as far as I can
tell, it's not much quicker.

Satish
0
 
peterkiersAuthor Commented:
crysallus, I want to ty your solution. I just begun with C# so I am not that good.
Is it possible to implement it without making use of a class.

P.
0
Cloud Class® Course: C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

 
peterkiersAuthor Commented:
       public static void LoadFromDataSet(TreeView tv, DataSet ds, string textColumnName)
        {
            TreeNode node;
            DataRow row;
            try
            {
                tv.Nodes.Clear();
                if (ds.Tables.Count < 1) { return; }
                if (ds.Tables[0].Rows.Count < 1) { return; }
                string fkcolumnname = FindForeignKeyColumnName(ds.Tables[0]);
                row = ds.Tables[0].Rows[0];
                tv.BeginUpdate();
                tv.TreeViewNodeSorter;          <================================
                node = GetTreeNodeFromDataRow(row, textColumnName);
                tv.Nodes.Add(node);
                AddNodeFromDataRow(node, row, textColumnName, FindForeignKeyRelationName(row.Table));
            }
            catch (Exception) { throw; }
            finally
            {
                tv.EndUpdate();
                ds.AcceptChanges();
            }
        }

I get error:Only assignment, call, increment, decrement, and new object expressions can be used as a statement      

P.
0
 
peterkiersAuthor Commented:
I have done this but I get errors:
        //*----------------------------------------------------------*//
        public class NodeSorter : IComparer
        {
            public int Compare(object x, object y)
            {
                TreeNode tx = x as TreeNode;
                TreeNode ty = y as TreeNode;
                if (tx.Text.Length != ty.Text.Length)
                    return tx.Text.Length - ty.Text.Length;
                return string.Compare(tx.Text, ty.Text);
            }
        }
        //*----------------------------------------------------------*//
        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            tvNotes.TreeViewNodeSorter = new NodeSorter();
        }
        //*----------------------------------------------------------*//

1.
Cannot implicitly convert type 'DbTreeView.MainForm.NodeSorter' to 'System.Collections.IComparer'. An explicit conversion exists (are you missing a cast?)      

2.
Using the generic type 'System.Collections.Generic.IComparer<T>' requires 1 type arguments      

Peter
0
 
crysallusCommented:
sounds like you are missing

using System.Collections;

Open in new window

BTW, setting the TreeViewNodeSorter property doesn't actually do the sorting, it just defines how it should be sorted when the time comes for it to be sorted. To actually sort it call the Sort() method if it's not doing it for you by default when you want it to.
0
 
peterkiersAuthor Commented:
"BTW, setting the TreeViewNodeSorter property doesn't actually do the sorting, it just defines how it should be sorted when the time comes for it to be sorted. To actually sort it call the Sort() method if it's not doing it for you by default when you want it to. "

How can I call the Sort() methode ???

Peter
0
 
crysallusCommented:
tvNotes.Sort();

no arguments required.
0
 
crysallusCommented:
The thing is when I used this before, I'm pretty sure the sorting was automatically done when I updated the TreeView's nodes, so I didn't have to manually call Sort() - which is why I didn't mention it earlier, because I didn't need to do it. I only mentioned it in case you wanted to manually force a sort in a non-default way, such as the click event which you posted earlier.
0
 
peterkiersAuthor Commented:
Thanks for the info.

Greetings, Peter Kiers
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 5
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now