I have two tables in database in relation 1:N and I want to populate treeview with data. The problem is how to add childs to each parent. This is my code:
private void PopulateTreeView()
{
try
{
DataTable dtProjekti = objDB.dbGetTable("SELECT * FROM tblProjekti");
DataTable dtAktivnosti = objDB.dbGetTable("SELECT * FROM tblprojektakt");
DataSet ds = new DataSet();
ds.Tables.Add(dtProjekti);
ds.Tables.Add(dtAktivnosti);
ds.Relations.Add("childrens", dtProjekti.Columns["OznakaProjekta"], dtAktivnosti.Columns["OznakaProjekta"]);
if (ds.Tables[0].Rows.Count > 0)
{
treeView1.Nodes.Clear();
foreach (DataRow masterRow in ds.Tables[0].Rows)
{
//TreeNode masterNode = new TreeNode((string)masterRow["ParentName"], Convert.ToString(masterRow["ParentId"]));
TreeNode masterNode = new TreeNode(masterRow["OznakaProjekta"].ToString());
treeView1.Nodes.Add(masterNode);
foreach (DataRow childRow in masterRow.GetChildRows("Children"))
{
// missing code for adding childs to each parent
}
}
}
}
catch (Exception ex)
{
throw new Exception("Unable to populate treeview" + ex.Message);
}
}
}
The childs are values from field Description.
I know how to manually add child to each parent but i stucked whan it should be dynamically.
The childs are values from field Description.
If you mean column Description. It should be something like this:
foreach (DataRow childRow in masterRow.GetChildRows("Children"))
{
masterNode.Nodes.Add(new TreeNode(childRow["Description"].ToString()));
}
Related
I am searching a PDF file for a keyword and returning the pages on which that keyword was found. If the keyword IS FOUND, I'm returning a list of pages and the fileName. However, if the keyword was NOT FOUND in the PDF file, I want to deleted the row in the datatable.
public DataTable dtPubSearchResultsFromFiles(string sqlQuery, string safeKeyword)
{
// Returns a datatable of publication search results based on PDF files.
SqlConnection con = new SqlConnection(getConnectionString());
SqlCommand cmd = new SqlCommand(sqlQuery, con);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
dt.Columns.Add("Pages", typeof(string));
da.Fill(dt);
dt.PrimaryKey = new DataColumn[] { dt.Columns["publicationID"] };
foreach (DataRow row in dt.Rows)
{
//call search function to look for keyword
List<int> myPages = new List<int>();
string fileName = row["linkToPublicationPDF"].ToString();
myPages = ReadPdfFile(fileName, safeKeyword);
if (myPages.Count > 0)
{
string pagelist = "";
foreach (int page in myPages)
{
pagelist = pagelist + page + " ";
}
row["Pages"] = pagelist;
}
else
{
//remove/delete the row from the datatable if "myPages.Count" is 0
dt.Rows.Remove(row);
}
}
return dt;
}
When I add this ("dt.Rows.Remove(row)"), I get this error when the page is called "System.InvalidOperationException: Collection was modified; enumeration operation might not execute."
Suggestions? Comments? Fixes? All are welcome...
Bob
Your code is getting some data from the database such that your program can work with it.
The exception you're getting is because your you're modifying (by removing an element) the collection you're iterating on and that's not possible.
You can solve this by creating a temporary List where you store the rows you want to delete. Once you're done with the iteration you can iterate on the temporary list and remove what you decided you don't want anymore.
var toRemove = new List<DataRow>();
foreach (DataRow row in dt.Rows)
{
//call search function to look for keyword
List<int> myPages = new List<int>();
string fileName = row["linkToPublicationPDF"].ToString();
myPages = ReadPdfFile(fileName, safeKeyword);
if (myPages.Count > 0)
{
string pagelist = "";
foreach (int page in myPages)
{
pagelist = pagelist + page + " ";
}
row["Pages"] = pagelist;
}
else
{
//remove/delete the row from the datatable if "myPages.Count" is 0
toRemove.Add(row);
}
}
}
foreach (DataRow row toRemove.Add)
{
dt.Rows.Remove(row);
}
try a simple Delete
row.Delete();
then after the loop
dt.AcceptChanges();
but it will probably fail
see answer from mario
it may work if it is really only marking the row for deletion
I am building nodes dynamically from a DB table. When I run the code the node root node also appears which wont go away. I have tried everything. Looked up on the internet but haven't find a specific solution for this problem.
My ProductCategory table looks like this
Here's the code in .cs file
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GetTreeViewItems();
}
}
private void GetTreeViewItems()
{
string cs = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
SqlConnection con = new SqlConnection(cs);
SqlDataAdapter da = new SqlDataAdapter("select * from ProductCategories where ParentId in (0,1,2)", con);
DataSet ds = new DataSet();
da.Fill(ds);
ds.Relations.Add("ChildRows", ds.Tables[0].Columns["ProductCategoryId"],
ds.Tables[0].Columns["ParentId"]);
foreach (DataRow level1DataRow in ds.Tables[0].Rows)
{
if (string.IsNullOrEmpty(level1DataRow["ParentId"].ToString()))
{
TreeNode parentTreeNode = new TreeNode();
parentTreeNode.Text = level1DataRow["ProductCategoryName"].ToString();
parentTreeNode.Value = level1DataRow["ProductCategoryId"].ToString();
parentTreeNode.NavigateUrl = "?catid=" + level1DataRow["ProductCategoryId"].ToString();
int i = (int)level1DataRow["ProductCategoryId"];
GetChildRows(level1DataRow, parentTreeNode);
TreeView1.Nodes.Add(parentTreeNode);
}
}
}
private void GetChildRows(DataRow dataRow, TreeNode treeNode)
{
DataRow[] childRows = dataRow.GetChildRows("ChildRows");
foreach (DataRow row in childRows)
{
TreeNode childTreeNode = new TreeNode();
childTreeNode.Text = row["ProductCategoryName"].ToString();
childTreeNode.Value = row["ProductCategoryId"].ToString();
childTreeNode.NavigateUrl = "?catid=" + row["ProductCategoryId"].ToString();
treeNode.ChildNodes.Add(childTreeNode);
if (row.GetChildRows("ChildRows").Length > 0)
{
GetChildRows(row, childTreeNode);
}
}
}
}
You can't do this. I you want a node to be invisible, but it's children to show, then the only way is not to add the root node, and add the children as root nodes.
Either that, or write your own TreeView control.
I have a menu control in my Master page.T he name of the menu and corresponding url is coming from the database. If a menu has a sub menu it is also showing properly.
But the problem arises if a sub menu has a child menu.
My database table has 4 columns
MenuId || MenuName || ParentId || URL.
and the code is
private void getMenu()
{
DataSet ds = new DataSet();
DataTable dt = new DataTable();
ds = objSec.ShowMenu(s_UserId);
dt = ds.Tables[0];
DataRow[] drowpar = dt.Select("ParentID=" + 0);
foreach (DataRow dr in drowpar)
{
menuBar.Items.Add(new MenuItem(dr["MenuName"].ToString(), dr["MenuID"].ToString(),
"", dr["URL"].ToString()));
}
foreach (DataRow dr in dt.Select("ParentID >" + 0))
{
try
{
MenuItem mnu = new MenuItem(dr["MenuName"].ToString(), dr["MenuID"].ToString(),
"", dr["URL"].ToString());
menuBar.FindItem(dr["ParentID"].ToString()).ChildItems.Add(mnu);
}
catch (Exception ex)
{
}
}
}
The approach in your sample might lead to incorrect results if sub-items are contained in the table before their parent-item. In addition, the empty catch-block might hide any errors. Therefore, I'd recommend another approach.
Instead of looping the table, you can also use recursion to fill the control. This removes the amount of duplicated code:
private void getMenu()
{
DataSet ds = objSec.ShowMenu(s_UserId);
DataTable dt = ds.Tables[0];
AddMenuItems(dt, 0, menu.Items);
}
private void AddMenuItems(DataTable dt, int parentId, MenuItemCollection items)
{
DataRow[] rows = dt.Select("ParentID=" + parentId.ToString());
foreach(var dr in rows)
{
var id = (int) dr["MenuID"];
var menuItem = new MenuItem(dr["MenuName"].ToString(), id.ToString(),
"", dr["URL"].ToString());
items.Add(menuItem);
// Add subitems
AddMenuItems(dt, id, menuItem.ChildItems);
}
}
The sample first calls the AddMenuItems method for the top-level items (ParentID = 0). After each item is added, its children are added by calling the AddMenuItems method again (hence the term "recursive"), providing the id of the top-level item as parent. For each 2nd level child, the method is called again and so on.
I am selecting a row from database. I want to add that row to a datagridview which has 3 columns in that row. I want to add those 3 columns to 3 rows.Can anyone can help? thanks!
this is my query
fillGrid("select selPriceCash1 as [Price 01] ,selPriceCash2 as [Price 02] ,selPriceCash3 as [Price 03] from tblItemInfo where code='" + itCode + "'");
And my code
private void fillGrid(string selectCmd)
{
try
{
BindingSource b = new BindingSource();
DataTable dt = cMethos.selectAtable(selectCmd);
b.DataSource = dt;
dgSend.DataSource = dt;
if (dt.Rows.Count < 0)
{
dgSend.Rows[0].Cells[0].Selected = true;
}
}
catch (Exception es)
{
MessageBox.Show(es.Message);
}
}
Not the prettiest but should work
private void fillGrid(string selectCmd)
{
List<string> Results = new List<string>();
DataTable dt = cMethos.selectAtable(selectCmd);
foreach(DataRow row in dt.Rows())
{
foreach (object rowObject in row.ItemArray)
{
Results.Add(rowObject.ToString());
}
}
dgSend.DataSource = Results;
}
I Want To Bind DataTable To TreeView.I Have Written Following Code.Its Working Currently,Means It Displays All Data Of DataTable But No Root Node.
List<DocumentData> lstData = GetSPDocuments();
gvDocuments.DataSource = lstData;
gvDocuments.DataBind();
DataTable dt = ConvertToDataTable(lstData);
TreeNode node1 = new TreeNode("Root");
foreach (DataRow r in dt.Rows)
{
int nodeLvl = int.Parse(r["ID"].ToString());
string nodeParent = "Folders";
string nodeName = r["Title"].ToString();
TreeNode tNode = new TreeNode(nodeName);
ht.Add(nodeLvl.ToString() + nodeName, tNode);
if (tvDocs.Nodes.Count == 0)
tvDocs.Nodes.Add(tNode);
else
{
nodeLvl--;
tvDocs.Nodes.Add(tNode);
}
}
How to Add Static Root Node Here??? Please Help!
Try this may be it can help you.
protected void Page_Load(object sender, EventArgs e)
{
conStr = ConfigurationManager.ConnectionStrings["conString"].ConnectionString;
conn = new OleDbConnection(conStr);
BindTreeViewControl();
}
private void BindTreeViewControl()
{
try
{
DataSet ds = GetDataSet("Select ProductId,ProductName,ParentId from ProductTable");
DataRow[] Rows = ds.Tables[0].Select("ParentId = 0");
for (int i = 0; i < Rows.Length; i++)
{
TreeNode root = new TreeNode(Rows[i]["ProductName"].ToString(), Rows[i]["ProductId"].ToString());
root.SelectAction = TreeNodeSelectAction.Expand;
CreateNode(root, ds.Tables[0]);
treeviwExample.Nodes.Add(root);
}
}
catch (Exception Ex) { throw Ex; }
}
public void CreateNode(TreeNode node, DataTable Dt)
{
DataRow[] Rows = Dt.Select("ParentId =" + node.Value);
if (Rows.Length == 0) { return; }
for (int i = 0; i < Rows.Length; i++)
{
TreeNode Childnode = new TreeNode(Rows[i]["ProductName"].ToString(), Rows[i]["ProductId"].ToString());
Childnode.SelectAction = TreeNodeSelectAction.Expand;
node.ChildNodes.Add(Childnode);
CreateNode(Childnode, Dt);
}
}
private DataSet GetDataSet(string Query)
{
DataSet Ds = new DataSet();
try
{
OleDbDataAdapter da = new OleDbDataAdapter(Query, conn);
da.Fill(Ds);
}
catch (Exception dex) { }
return Ds;
}
and database structure for this is
// Suppress repainting the TreeView until all the objects have been created.
treeView1.BeginUpdate();
// Clear the TreeView each time the method is called.
treeView1.Nodes.Clear();
// create root node
TreeNode root = new TreeNode("Root");
// loop and add all child nodes to root node
foreach (DataRow r in dt.Rows)
{
// create child node
// add to root node
root.Nodes.Add(child);
}
// add root node to tree view
treeView1.Nodes.Add(root);
// Begin repainting the TreeView.
treeView1.EndUpdate();
Did you ever get this answered? You were almost there.
What is the name of your TreeView control? Since you never said, I am using treeView1, and modified your code to include that below:
private TreeView treeView1;
private void TreeView_DataBind() {
treeView1.Nodes.Clear();
List<DocumentData> lstData = GetSPDocuments();
gvDocuments.DataSource = lstData;
gvDocuments.DataBind();
DataTable dt = ConvertToDataTable(lstData);
TreeNode node1 = new TreeNode("Root");
treeView1.Nodes.Add(node1); // this is the step you missed
foreach (DataRow r in dt.Rows)
{
int nodeLvl = int.Parse(r["ID"].ToString());
string nodeParent = "Folders";
string nodeName = r["Title"].ToString();
TreeNode tNode = new TreeNode(nodeName);
ht.Add(nodeLvl.ToString() + nodeName, tNode);
if (tvDocs.Nodes.Count == 0)
tvDocs.Nodes.Add(tNode);
else
{
nodeLvl--;
tvDocs.Nodes.Add(tNode);
}
}
node1.Expand();
}
Easy peasy!