Note that there are some explanatory texts on larger screens.

plurals
  1. POPopulate WinForms TreeView from DataTable
    primarykey
    data
    text
    <p>I have a WinForm TreeView Control that displays the Parent Child relationship of CaseNotes(I know that means nothing to most of you but it helps me visualize the answers). </p> <p>I have a DataTable of the CaseNotes that I need to display. The Parent/Child is defined as: If the row has a ParentNoteID then it is a childNode of that note otherwise it is a rootNode. It could also be a parent note(but not a rootNode) if another row has it's ID as it's ParentNoteID.</p> <p>To complicate(maybe simplify) things I have the below working(mostly) code that colors the nodes alternatingly. I manually created a static collection for the treeview and it colors them fairly correctly. Now I need to dynamically populate the Nodes from my DataTable.</p> <p>Since I already am going thru the treeview node by node shouldn't I be able to append the data into this process somehow? Maybe I need to build the nodes first and then color as a separate routine but the Recursion Method would still apply, correct?</p> <p>Lets say I want to display CaseNoteID for each Node. That is returned in the DataTable and is unique.</p> <pre><code>foreach (TreeNode rootNode in tvwCaseNotes.Nodes) { ColorNodes(rootNode, Color.MediumVioletRed, Color.DodgerBlue); } protected void ColorNodes(TreeNode root, Color firstColor, Color secondColor) { root.ForeColor = root.Index % 2 == 0 ? firstColor : secondColor; foreach (TreeNode childNode in root.Nodes) { Color nextColor = childNode.ForeColor = childNode.Index % 2 == 0 ? firstColor : secondColor; if (childNode.Nodes.Count &gt; 0) { // alternate colors for the next node if (nextColor == firstColor) ColorNodes(childNode, secondColor, firstColor); else ColorNodes(childNode, firstColor, secondColor); } } } </code></pre> <h2>EDIT</h2> <p>My thoughts/attempts so far: </p> <pre><code> public void BuildSummaryView() { tvwCaseNotes.Nodes.Clear(); DataTable cNotesForTree = CurrentCaseNote.GetAllCNotes(Program._CurrentPerson.PersonID); foreach (var cNote in cNotesForTree.Rows) { tvwCaseNotes.Nodes.Add(new TreeNode("ContactDate")); } FormPaint(); } </code></pre> <p>Obviously this is flawed. One it just display's ContactDate over and over. Granted it shows it the correct number of times but I would like the Value of ContactDate(which is a Column in the database and is being returned in the DataTable. Second I need to add the ChildNode Logic. A <code>if (node.parentNode = node.CaseNoteID) blah...</code></p> <h2>EDIT 2</h2> <p>So I found this link, <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.treeview.beginupdate(VS.85).aspx" rel="noreferrer">here</a>, and it makes it seem like I need to get my DataTable into an ArrayList. Is that correct?</p> <h2>EDIT 3</h2> <p>Okay, thanks to Cerebus this is mostly working. I just have one more question. How do I take this--></p> <pre><code>DataTable cNotesForTree = CurrentCaseNote.GetAllCNotes(Program._CurrentPerson.PersonID); </code></pre> <p>and use my returned DataTable in this? Do I just replace this --></p> <pre><code> dt = new DataTable("CaseNotes"); dt.Columns.Add("NoteID", typeof(string)); dt.Columns.Add("NoteName", typeof(string)); DataColumn dc = new DataColumn("ParentNoteID", typeof(string)); dc.AllowDBNull = true; dt.Columns.Add(dc); // Add sample data. dt.Rows.Add(new string[] { "1", "One", null }); dt.Rows.Add(new string[] { "2", "Two", "1" }); dt.Rows.Add(new string[] { "3", "Three", "2" }); dt.Rows.Add(new string[] { "4", "Four", null }); dt.Rows.Add(new string[] { "5", "Five", "4" }); dt.Rows.Add(new string[] { "6", "Six", null }); dt.Rows.Add(new string[] { "7", "Seven", null }); dt.Rows.Add(new string[] { "8", "Eight", "7" }); dt.Rows.Add(new string[] { "9", "Nine", "8" }); </code></pre> <p>My confusion, I think, is do I still need to do the Column.Add and Row.Adds? Also how would the DataColumn translate to my real data structure? Sorry for the very ignorant questions, the good news is I never have to ask twice.</p> <h2>EDIT 4</h2> <p>The following is providing a runtime error. </p> <pre><code>if (nodeList.Find(FindNode) == null) { DataRow[] childRows = dt.Select("ParentNoteID = " + dr["NoteID"]); if (childRows.Length &gt; 0) { // Recursively call this function for all childRowsl TreeNode[] childNodes = RecurseRows(childRows); // Add all childnodes to this node. node.Nodes.AddRange(childNodes); } // Mark this noteID as dirty (already added). //doneNotes.Add(noteID); nodeList.Add(node); } </code></pre> <p>The error is as follows --> <strong><em>Cannot find column [ea8428e4]</em></strong> Which is the first 8 digits of the correct NoteID(I have to use a Guid). Should it be looking for a column of that name?? Because I am using a Guid is there something else I need to do? I changed all the references in mine and your code to Guid...</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload