I have this treeview control where I want to put uploaded files on the server.
I want to be able to create the nodes and the child nodes dynamically from the database.
I am using this query for getting the data from DB:
SELECT c.Category, d.DocumentName FROM Categories c
INNER JOIN DocumentUserFile d
ON c.ID = d.CategoryId
WHERE d.UserId = '9rge333a-91b5-4521-b3e6-dfb49b45237c'
The result from that query is this one:
Agendas
transactions.pdf
Minutes
accounts.pdf
I want to have the treeview sorted that way too.
I am trying with this piece of code:
TreeNode tn = new TreeNode();
TreeNode tnSub = new TreeNode();
foreach (DataRow dt in tblTreeView.Rows)
{
tn.Text = dt[0].ToString();
tn.Value = dt[0].ToString();
tnSub.Text = dt[1].ToString();
tnSub.NavigateUrl = "../downloading.aspx?file=" + dt[1].ToString() +"&user=" + userID;
tn.ChildNodes.Add(tnSub);
tvDocuments.Nodes.Add(tn);
}
I am getting the treeview populated nicely for the 1st category and the document under that category, but I can't get it to work when I want to show more documents under that category, or even more complicate to show new category beneath the 1st one with documents from that category.
How can I solve this?
I appreciate the answers a lot.
Thanks, Laziale
You should create new nodes for each item:
// TreeNode tn = new TreeNode();
// TreeNode tnSub = new TreeNode();
foreach (DataRow dt in tblTreeView.Rows)
{
TreeNode tn = new TreeNode(); // *
tn.Text = dt[0].ToString();
tn.Value = dt[0].ToString();
TreeNode tnSub = new TreeNode(); // *
tnSub.Text = dt[1].ToString();
tnSub.NavigateUrl = "../downloading.aspx?file=" + dt[1].ToString() +"&user=" + userID;
tn.ChildNodes.Add(tnSub);
tvDocuments.Nodes.Add(tn);
}
Related
I have a tree view, which I'm populating using a server side method taking values from the DB.
The tree view gets populated and works fine.
I'm trying to access the Tree View nodes inside a foreach loop, but to my surprise, the count property shows value as 1.
PFB the codes:
public void PopulateTreeView()
{
DataSet ds = new DataSet();
DataTable dtUltimateParent = GetUltimateParent();
DataTable dtA = GetParent();
DataTable dtB = GetChildren();
DataTable dt1 = new DataTable();
DataTable dt2 = new DataTable();
DataTable dt3 = new DataTable();
dt1 = dtUltimateParent.Copy();
dt2 = dtA.Copy();
dt3 = dtB.Copy();
ds.Tables.Add(dt1);
ds.Tables.Add(dt2);
ds.Tables.Add(dt3);
ds.Relations.Add("FirstHierarchy", dt1.Columns["ultimateParentID"], dt2.Columns["ParentID"]);
ds.Relations.Add("SecondHierarchy", dt2.Columns["ParentID"], dt3.Columns["ChildID"]);
if (ds.Tables[0].Rows.Count > 0)
{
TreeView1.Nodes.Clear();
foreach (DataRow ultimateRow in ds.Tables[0].Rows)
{
TreeNode ultimateNode = new TreeNode((string)ultimateRow["ultimateParentText"], Convert.ToString(ultimateRow["ultimateParentID"]));
TreeView1.Nodes.Add(ultimateNode);
ultimateNode.Expanded = true;
ultimateNode.SelectAction = TreeNodeSelectAction.None;
foreach (DataRow masterRow in ultimateRow.GetChildRows("FirstHierarchy"))
{
TreeNode masterNode = new TreeNode((string)masterRow["ParentText"], Convert.ToString(masterRow["ParentID"]));
ultimateNode.ChildNodes.Add(masterNode);
masterNode.Value = Convert.ToString(masterRow["ParentID"]);
masterNode.Expanded = false;
masterNode.SelectAction = TreeNodeSelectAction.None;
foreach (DataRow childRow in masterRow.GetChildRows("SecondHierarchy"))
{
TreeNode childNode = new TreeNode((string)childRow["ChildText"], Convert.ToString(childRow["ChildID"]));
masterNode.ChildNodes.Add(childNode);
childNode.Value = Convert.ToString(childRow["Child"]);
}
}
}
}
}
Now I am trying to access the Nodes using a foreach loop like below:
string[] myArray=an array having the texts of the Nodes
foreach(TreeNode node in TreeView1.Nodes)
{
foreach(string s in myArray)
{
if(s==node.Text)
{
node.checked=true;
}
}
}
TreeView1.Nodes shows only one node which is 'All', also TreeView1.Nodes.Count comes as 1, but the whole tree view is populated and is pretty visible.
The Tree View is something like:
All
A
a1
a2
B
b1
b2
Am I doing the correct way to iterate amongst the tree view nodes?
Experts please guide over here.
Regards
Anurag
All
A
a1
a2
B
b1
b2
TreeView1.Nodes //this shows the upper hierarchy...to access the nodes under All
you should use
TreeView1.Nodes[0].Nodes //this will show the nodes under All that means
A and B......so correct your code this way
TreeView1.Nodes[0].Nodes[0].Nodes.......a1 and a2
I have a SQL table looking like this:
orderID customerName orderDate valueTotal
================================================================
1 JohnA 01/02/2013 100
2 AmandaF 01/02/2013 140
3 JohnA 05/03/2013 58
4 FredM 05/03/2013 200
And I want to order this information on a treeView by either orderDate or customerName, depending on user settings so that it looks like this if ordered by customerName:
JohnA
01/02/2013
05/03/2013
AmandaF
01/02/2013
FredM
05/03/2013
Or like this if ordered by orderDate:
01/02/2013
JohnA
AmandaF
05/03/2013
JohnA
FredM
What would be the best way to achieve this?
EDIT:
I'm using windows forms
If you're using ADO.Net, test this:
Dictionary<string, List<string>> groups = new Dictionary<string, List<string>>();
//set these dynamic
string groupingFieldName = "customerName";
string targetFieldName = "orderDate";
SqlDataReader rdr = sqlCmd.ExecuteReader();
while (rdr.Read())
{
if (!groups.ContainsKey(rdr[groupingFieldName].ToString()))
{
groups.Add(rdr[groupingFieldName].ToString(), new List<string>());
}
groups[rdr[groupingFieldName].ToString()].Add(rdr[targetFieldName].ToString());
}
//next, iterate the dictionary and populate the treeView
foreach (KeyValuePair<string, List<string>> group in groups)
{
//add to treeView
}
Please note that this is not tested. You still need to test it.
I've ended up creating two functions to perform this in a more dynamic and scalable way.
public static TreeNodeCollection SqlToTreeNodeHierarchy(this SqlDataReader dataReader, TreeNode parent)
{
// create a parent TreeNode if we don't have one, so we can anchor the new TreeNodes to it
// I think this will work better than a list since we might be given a real parent..
if (parent == null)
{
parent = new TreeNode("topNode");
}
while (dataReader.Read())
{
//at the beginning of each row, reset the parent
var parentNode = parent;
for (var i = 0; i < dataReader.FieldCount; i++)
{
// Adds a new TreeNode as a child of parentNode if it doesn't already exist
// at this level, else it will return the existing TreeNode and save
// it onto parentNode. This way, subsequent TreeNodes will always be a child
// of this one, until a new row begins and the parent TreeNode is reset.
parentNode = AddUniqueNode(dataReader[i].ToString(), parentNode);
}
}
return parent.Nodes;
}
public static TreeNode AddUniqueNode(string text, TreeNode parentNode)
{
// if parentNode is null, create new treeNode and return it
if (parentNode == null)
{
return new TreeNode {Name = text, Text = text};
}
// if parentNode is not null, do a find for child nodes at this level containing the key
// we're after (text and name have the same value) and return the first one it finds
foreach (var childNode in parentNode.Nodes.Find(text, false))
{
return childNode;
}
// Node does not yet exist, so just add a new node to the parentNode and return that
return parentNode.Nodes.Add(text, text);
}
Then I just need to call the functions as follows:
using (var sqlConn = new SqlConnection(connectionString))
{
sqlConn.Open();
const string query = "SELECT orderDate, customerName from MAIN";
using (var sqlCommand = new SqlCommand(query, sqlConn))
{
using (var sqlDataReader = sqlCommand.ExecuteReader())
{
var treeNodeCollection = sqlDataReader.SqlToTreeNodeHierarchy(null);
foreach (TreeNode treeNode in treeNodeCollection)
{
nativeTreeView.Nodes.Add(treeNode);
}
}
}
}
This way I can make it scale with as many child nodes as I want and it also gives me the flexibility of loading the child nodes only when on expand by doing another SQL query and passing the parent as the TreeNode that was just expanded.
I don't know what I'm missing on this:
I have this relationship in my EDM- (can't load a picture yet)
Category_1__many RecipeCategory_many__1_Recipe
Basically every recipe has one or more categories and every category can have 0 or more recipes
Here's my code:
private void LoadData()
{
List<Category> Categories = new List<Category>();
List<Recipe> Recipes = new List<Recipe>();
var ctx = new MaWEntities();
var query = from x in ctx.Categories select x;
Categories = query.ToList<Category>();
foreach (Category c in Categories)
{
TreeViewItem TVP = new TreeViewItem() { Header = c.CategoryName.ToString() };
var qq = from xx in ctx.RecipeCategories.Where(o => o.CategoryId == c.CategoryId) select xx;
foreach (var rc in qq)
{
TreeViewItem TVC = new TreeViewItem() { Header = rc.Recipe.RecipeName.ToString() };
TVP.Items.Add(TVC);
//TVP.IsExpanded = true;
}
}
}
What I am trying to accomplish is a treeview whose parent nodes are the categoryname and child nodes are the recipe name. I know how drill into a relational table from a base table (Recipe to RecipeCategory) using Linq. There MUST also be a way to traverse again to the Category table too. I should also mention that even if the Category does not have any Recipes I still want to see the Category Name as a parent in the treeview.
I found that my problem in this scenario was not that my code wasn't working; rather that I neglected to ever add the treeview items to my treeview. Also, this addition needs to be done after the foreach loop. List Categories = new List();
List Recipes = new List();
var ctx = new MaWEntities();
var query = from x in ctx.Categories select x;
Categories = query.ToList<Category>();
foreach (Category c in Categories)
{
TreeViewItem TVP = new TreeViewItem() { Header = c.CategoryName.ToString() };
var query2 = from xx in ctx.RecipeCategories.Where(o => o.CategoryId == c.CategoryId) select xx;
foreach (var rc in query2)
{
TreeViewItem TVC = new TreeViewItem() { Header = rc.Recipe.RecipeName.ToString() };
TVP.Items.Add(TVC);
}
tvwRecipe.Items.Add(TVP);
}
I have a treeview and i want no postback on click any childnodes.And i will get selected childnode value.
I found a solution , when i set "node_.SelectAction = TreeNodeSelectAction.None;" i cant select any childnodes and no highlight on it.
Waiting your helps.Sorry about my en.
Aspx:
<asp:TreeView ID="TreeView1" runat="server"></asp:TreeView>
Cs:
TreeView1.Nodes.Clear();
TreeView1.TreeNodeExpanded += new TreeNodeEventHandler(TreeView1_TreeNodeExpanded);
DataTable dt = ImzaDll.Imza.KategorileriGetir(true);
foreach (DataRow row in dt.Rows)
{
TreeNode node_ = new TreeNode();
node_.Text = row["ACIKLAMA"].ToString();
node_.Value = row["KATEGORI"].ToString();
TreeView1.Nodes.Add(node_);
}
void TreeView1_TreeNodeExpanded(object sender, TreeNodeEventArgs e)
{
addChildNodes(e.Node);
}
private void addChildNodes(TreeNode node)
{
DataTable dt = ImzaDll.Imza.KutuphaneBasliklariGetir(true, node.Value.ToString());
foreach (DataRow row in dt.Rows)
{
TreeNode childNode = new TreeNode();
childNode.Text = row["BASLIK"].ToString();
childNode.Value = row["KUTUPHANE_ID"].ToString();
childNode.ToolTip = row["BASLIK"].ToString() + " kütüphanesini ekle";
childNode.Target = "_new";
node.ChildNodes.Add(childNode);
}
}
You can set CSSClass of treeview child nodes
like
<asp:TreeView LeafNodeStyle-CssClass="childnode" runat="server">....</asp:TreeView>
then using jquery you get get class and set return false like follow.
$(".childnode").click(function(){
return false;
})
...same way you can set RootNodeStyle-CssClass, ParentNodeStyle-CssClass class and use jquery to set them...
TreeNode tn = new TreeNode();
tn.SelectAction = TreeNodeSelectAction.None; OR tn.SelectAction = TreeNodeSelectAction.Expand;
Both of these will not cause postback.
you could remove the href of link('a') tag attribute to stop post back
$('#ctl00_ContentPlaceHolder1_tvHierarchyView table tr td>a').click(function () {
var treeViewData = window["<%=tvHierarchyView.ClientID%>" + "_Data"];
if (treeViewData.selectedNodeID.value != "") {
var selectedNode=document.getElementById(treeViewData.selectedNodeID.value);
var value = selectedNode.href.substring(selectedNode.href.indexOf(",") + 3, selectedNode.href.length - 2);
var text = selectedNode.innerHTML;
alert("Text: " + text + "\r\n" + "Value: " + value);
} else {
alert("No node selected.")
}
$(this).removeAttr("href");
/// ...................... rest of your code
}); /// End of click function
}); /// End of document ready function
Here steps explanation:
Get the dev id which contains the tree table by Using inspect element:
Get details from the selected child node.
After taken the details of child node , remove the attribute "href" to avoid post back.
Do whatever functionality you what do with selected node details (eg pass selected value using ajax)
Is there a way I can keep the text of a Parent node but remove the link? The treeview parent node is used just as a header, no navigation. Any help would be great. Thanks.
private void BindNodes(string PtID)
{
if (PtID != "")
{
int PatientID = Convert.ToInt32(PtID);
DBConnection dbObj = new DBConnection();
if (Session["Activepatient"] != null)
{
string[] SubChild = new string[4];
SubChild[0] = "Demographics";
SubChild[1] = "Medication Reviews";
SubChild[2] = "Drug Testing & Monitoring";
SubChild[3] = "Other Program";
TreeNode oTrParent = new TreeNode();
//trv_patient.ParentNodeStyle = "None";
//oTrParent.SelectAction.Style.Add("display", "none");
TreeNode oTrSubChild1;
TreeNode oTrSubChild;
for (int i = 0; i < 4; i++)
{
oTrSubChild1 = new TreeNode();
oTrSubChild1.Text = SubChild[i];
if (i == 1)
{
PatientInfoCollection patientCollection = new PatientInfoCollection();
patientCollection = dbObj.GetMedicationReviews(PatientID);
foreach (PatientInfo au in patientCollection)
{
oTrSubChild = new TreeNode();
PatientInfo Patient = new PatientInfo();
oTrSubChild.Text = au.DateRcvd.Value.ToString("MM-dd-yyyy")
oTrSubChild.Target = au.ReviewId.ToString();
oTrSubChild1.ChildNodes.Add(oTrSubChild);
}
oTrSubChild = new TreeNode();
oTrSubChild.Text = "Add Medication Review";
oTrSubChild.Target = "New";
oTrSubChild1.ChildNodes.Add(oTrSubChild);
}
trv_patient.Nodes.Add(oTrSubChild1);
}
}
}
}
If temp is such node whose text you want to be plain text and not link then use code below.
TreeNode temp = new TreeNode("text");
temp.SelectAction = TreeNodeSelectAction.None;
treeView1.Nodes.Add(temp);
This is what your looking for. You have to set the SelectAction of the parent node TreeNode to TreeNodeSelectAction.None. I even show how to do it with the child too.
ASP.NET
<asp:TreeView
ID="MyTreeView"
ShowCheckBoxes="Parent,Leaf,All"
runat="server"
ShowLines="true"
ShowExpandCollapse="true">
</asp:TreeView>
C#
//Make A Parent Node
var Parent = new TreeNode();
Parent.Text = "Parent 1";
// Make the parent nodes not be hyperlinks but plain text
Parent.SelectAction = TreeNodeSelectAction.None;
//You can do the same with a child node like so
var Child = new TreeNode();
Child.Text = "Child 1";
// Make the child nodes not be hyperlinks but plain text
Child.SelectAction = TreeNodeSelectAction.None;
//Add the child node to the parent node
Parent.ChildNodes.Add(Child);
//Finally add the parent node with children to the treeview
MyTreeView.Nodes.Add(Parent);
I'm not sure if I understand what you want. Assuming that it's WinForms and that you just want to disable the ability to select the root node in a TreeView you could just handle the BeforeSelect event of the TreeView and then have the following code:
if (e.Node.Parent == null)
e.Cancel = true;
TreeNode root = new TreeNode("Root");
root.SelectAction = TreeNodeSelectAction.None;