Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

How to sort a treeview alfabeticly

Posted on 2011-03-16
10
Medium Priority
?
761 Views
Last Modified: 2013-12-17
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
Comment
Question by:peterkiers
  • 5
  • 4
10 Comments
 
LVL 8

Accepted Solution

by:
crysallus earned 1800 total points
ID: 35145834
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
 

Assisted Solution

by:satishmp
satishmp earned 200 total points
ID: 35145881
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
 
LVL 1

Author Comment

by:peterkiers
ID: 35145994
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 1

Author Comment

by:peterkiers
ID: 35146012
       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
 
LVL 1

Author Comment

by:peterkiers
ID: 35146052
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
 
LVL 8

Expert Comment

by:crysallus
ID: 35146107
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
 
LVL 1

Author Comment

by:peterkiers
ID: 35146147
"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
 
LVL 8

Expert Comment

by:crysallus
ID: 35146325
tvNotes.Sort();

no arguments required.
0
 
LVL 8

Expert Comment

by:crysallus
ID: 35146398
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
 
LVL 1

Author Comment

by:peterkiers
ID: 35146431
Thanks for the info.

Greetings, Peter Kiers
0

Featured Post

Microsoft Certification Exam 74-409

Veeam® is happy to provide the Microsoft community with a study guide prepared by MVP and MCT, Orin Thomas. This guide will take you through each of the exam objectives, helping you to prepare for and pass the examination.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article aims to explain the working of CircularLogArchiver. This tool was designed to solve the buildup of log file in cases where systems do not support circular logging or where circular logging is not enabled
Simulator games are perfect for generating sample realistic data streams, especially for learning data analysis. It is even useful for demoing offerings such as Azure stream analytics, PowerBI etc.
Want to learn how to record your desktop screen without having to use an outside camera. Click on this video and learn how to use the cool google extension called "Screencastify"! Step 1: Open a new google tab Step 2: Go to the left hand upper corn…
This lesson discusses how to use a Mainform + Subforms in Microsoft Access to find and enter data for payments on orders. The sample data comes from a custom shop that builds and sells movable storage structures that are delivered to your property. …
Suggested Courses

877 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question