4

i create a simple table such as image below

enter image description here

and fill by item such as image below

enter image description here

load this table in tree view on c# form application by using microsoft.sqlserver.types.10.50.1600.1 nuget and work fin

enter image description here

my problem is i don't know how to convert tree view to hierarchyid in c#. i search on internet but all of description for hierarchyid in sql-server. i use tree view path but that return string for example : node car repairman return:Manager/NT/NT& Transportation Expert/Car repairman but i want return /1/1/2/ to store in my table and second problem that how to traversal all brunch node to update table when insert or delete . my code to load data to treeview is:

namespace TVHierachyID
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        DataTable dataTable4;
        private BindingSource oBS = new BindingSource();
        private void btnGetData_Click(object sender, EventArgs e)
        {
            SqlConnection cs4 = new SqlConnection("Data Source=1.1.1.1;Network Library=DBMSSOCN;Initial Catalog=test;User ID=test;Password=test");
            SqlDataAdapter adapter4 = new SqlDataAdapter("select unit_name,lvl,lvl.ToString()as lvls,lvl.GetLevel()as lvln from test_tbl", cs4);
             dataTable4 = new DataTable();
            adapter4.Fill(dataTable4);            
            oBS.DataSource = dataTable4;
            dgData.DataSource = oBS;
            lblCount.Text = string.Format("{0} records loaded", oBS.Count);
        }
        private void doTV_Click(object sender, EventArgs e)
        {
            string sKeyField = "lvl", sTextField = "lvls";
            LoadTreeSQLHierarchy(this.tvData, dataTable4,sKeyField,sTextField);
        }
        /// <summary>
        /// Uses Linq to filter the table
        /// additional info from: http://nesteruk.org/blog/post/Working-with-SQL-Server-hierarchical-data-and-Silverlight.aspx#Reference6
        /// </summary>
        /// <param name="oTV">Treeview to load</param>
        /// <param name="oTable">datatable with the nodekey</param>
        private void LoadTreeSQLHierarchy(TreeView oTV, DataTable oTable, string sKeyField, string sTextField)
        {
            oTV.Nodes.Clear();
            TreeNode oNode;
            SqlHierarchyId iID = new SqlHierarchyId();
            EnumerableRowCollection<DataRow> query = from TNodes in oTable.AsEnumerable()                                                                                            where TNodes.Field<SqlHierarchyId>(sKeyField).GetAncestor(1).Equals(iID)
                                                     select TNodes;

            DataView oDV = query.AsDataView();
            if (oDV.Count == 1)
            {               
                oNode = new TreeNode(oDV[0][0].ToString());
                oNode.Tag = oDV[0].Row;
                LoadNodeSQLHierarchy(oNode, oTable);
                oTV.Nodes.Add(oNode);
            }
        }
        /// <summary>
        /// Load up the children 
        /// </summary>
        /// <param name="oParent">parent node</param>
        /// <param name="oTable">datatable with the nodekey</param>
        private void LoadNodeSQLHierarchy(TreeNode oParent, DataTable oTable)
        {
            oParent.Nodes.Clear();
            SqlHierarchyId iID = new SqlHierarchyId();
            DataRow oRow = (DataRow)oParent.Tag;
            iID = (SqlHierarchyId)oRow["lvl"];
            EnumerableRowCollection<DataRow> query = from order in oTable.AsEnumerable()
                                                     where order.Field<SqlHierarchyId>("lvl").GetAncestor(1).Equals(iID)
                                                     select order;
            DataView oDV = query.AsDataView();
            foreach (DataRowView oDR in oDV)
            {
                TreeNode oNode = new TreeNode(oDR["unit_name"].ToString());
                oNode.Tag = oDR.Row;
                LoadNodeSQLHierarchy(oNode, oTable);
                oParent.Nodes.Add(oNode);
            }
        }       
    }
}
  • 2
    How did you build the tree view? Please show the code for building the tree view. You need to traverse the tree view in order to build the hierarchy again - you have it, because you are showing it. Where and how is the level stored in the tree view / tree node? – keenthinker Apr 20 '20 at 06:58
  • Does this answer your question? [How to generate MSSQL Hierarchy ID for each element for a tree object](https://stackoverflow.com/questions/25856282/how-to-generate-mssql-hierarchy-id-for-each-element-for-a-tree-object) – Sunny Sharma Apr 20 '20 at 07:03
  • 2
    TreeNode object has a Tag property (type of object) and you can put an instance of a custom class in it which can contain the level information (/1/1/2) . Can you please share your code where you are populating the tree view? – Oguz Ozgul Apr 20 '20 at 07:03
  • i edit post and set my code:) – Mehrdad b.h Apr 20 '20 at 08:22
  • Your tree node instances already has the corresponding Row in their Tag property. This is not a best practice because you will be keeping the row and along with it the table holding it in memory for good. Anyways, the source code already gets the Tag of the oParent `DataRow oRow = (DataRow)oParent.Tag;` and also gets the Lvl field. Isn't this what you need? – Oguz Ozgul Apr 20 '20 at 09:01
  • my problem is i don't know how to use it:) whats properties content this i need to traversal all nods or check only tags and update them – Mehrdad b.h Apr 20 '20 at 09:25
  • Are you asking how to take data from the Tree View (which may have been manipulated or added to after it was loaded) and regenerate the `lvl` so that you can store it back to the database? – Enigmativity Apr 20 '20 at 10:06
  • yes exactly enigmativity – Mehrdad b.h Apr 20 '20 at 10:38

2 Answers2

0

solved by this Maybe others will use it:X

private void buttonsave_Click(object sender, EventArgs e)
    {
        TreeNode oMainNode = tvData.Nodes[0];
        PrintNodesRecursive(oMainNode);
        fsave = true;
    }

 public void PrintNodesRecursive(TreeNode oParentNode)
    {
        // Start recursion on all subnodes.
        foreach (TreeNode oSubNode in oParentNode.Nodes)
        {
            TreeNode node = oSubNode;
            while (node != null)
            {
                path2.Push(node.Index.ToString());
                node = node.Parent;
            }
            string nodePath = string.Join("/", path2.ToArray()) + "/";
            nodePath = nodePath.Remove(0, 1);
            MessageBox.Show(nodePath, oSubNode.Text);
            path2.Clear();
            PrintNodesRecursive(oSubNode);
        }
    }
0

This might be a slightly cleaner way:

public IEnumerable<TreeNode> GetTreeNodeParentPath(TreeNode oParentNode)
{
    if (oParentNode != null)
    {
        yield return oParentNode;
        foreach (var node in GetTreeNodeParentPath(oParentNode.Parent))
            yield return node;
    }
}

public void PrintNodesRecursive(TreeNode oParentNode)
{
    foreach (TreeNode oSubNode in oParentNode.Nodes)
    {
        var message = String.Concat(GetTreeNodeParentPath(oSubNode).Select(x => $"{x.Index}/"));
        MessageBox.Show((message), oSubNode.Text);
        PrintNodesRecursive(oSubNode);
    }
}
Enigmativity
  • 113,464
  • 11
  • 89
  • 172