Treeview from DataTable - c#

Hi have a data Table with 3 fields and my expected tree view will like this below image.
My data table returns the details like this.
And i tried the below code. Here child node not getting listing properly
public void BuildTree(DataTable dt, TreeView trv, Boolean expandAll)
{
trv.Nodes.Clear();
TreeNode node = default(TreeNode);
TreeNode subNode = default(TreeNode);
foreach (DataRow row in dt.Rows)
{
node = Searchnode(row[0].ToString(), trv);
if (node != null)
{
subNode = new TreeNode(row[1].ToString());
node.Nodes.Add(subNode);
}
else
{
node = new TreeNode(row[0].ToString());
subNode = new TreeNode(row[1].ToString());
node.Nodes.Add(subNode);
trv.Nodes.Add(node);
}
}
if (expandAll)
{
trv.ExpandAll();
}
}
private TreeNode Searchnode(string nodetext, TreeView trv)
{
foreach (TreeNode node in trv.Nodes)
{
if (node.Text == nodetext)
{
return node;
}
}
return null;
}

I'm suposing that datatable is previosly ordered by CustomerName, DeliverySchedule, Name
Initialize test data:
private void InitializeDataTable() {
dt = new DataTable();
dt.Columns.Add("DeliverySchedule");
dt.Columns.Add("Name");
dt.Columns.Add("CustomerName");
AddRow("Daily", "Test", "Team Venkat");
AddRow("Daily", "TestB", "Team Venkat");
AddRow("Weekly", "OtherName", "Team Venkat");
AddRow("Weekly", "OtherName2", "Team Venkat");
AddRow("Daily", "Test", "Team2");
AddRow("Weekly", "Test", "Team2");
}
private void AddRow(string schedule, string name, string customer) {
DataRow row = dt.NewRow();
row[0] = schedule;
row[1] = name;
row[2] = customer;
dt.Rows.Add(row);
}
Load tree from DataTable using a three level loop:
private void LoadBtn_Click(object sender, EventArgs e) {
int i = 0;
treeView1.Nodes.Clear();
while (i < dt.Rows.Count) {
DataRow row = dt.Rows[i];
string customer = row.Field<string>(2);
TreeNode customerNode = treeView1.Nodes.Add(customer);
while (i < dt.Rows.Count && row.Field<string>(2) == customer) {
string schedule = row.Field<string>(0);
TreeNode scheduleNode = customerNode.Nodes.Add(schedule);
while (i < dt.Rows.Count && row.Field<string>(2) == customer && schedule == row.Field<string>(0)) {
string report = row.Field<string>(1);
scheduleNode.Nodes.Add(report);
if (++i < dt.Rows.Count)
row = dt.Rows[i];
}
}
}
}

Related

Text file as datasource to display data in gridview

Text file data looks like below:
FacilityID:12787 FacilityName:ACME Medical Center FacilityLocation:XYZ
FacilityID:27875 FacilityName:Medical Center FacilityLocation:kh
private void ReadFile(string fileName)
{
var rows = System.IO.File.ReadAllLines(fileName);
Char[] separator = new Char[] { ':' };
DataTable tbl = new DataTable(fileName);
if (rows.Length != 0)
{
foreach (string headerCol in rows[0].Split(separator[0]))
{
tbl.Columns.Add(new DataColumn(headerCol));
}
if (rows.Length > 1)
{
for (int rowIndex = 1; rowIndex < rows.Length; rowIndex++)
{
var newRow = tbl.NewRow();
var cols = rows[rowIndex].Split(separator);
for (int colIndex = 0; colIndex < cols.Length; colIndex++)
{
newRow[colIndex] = cols[colIndex];
}
tbl.Rows.Add(newRow);
}
}
}
}
To add data in datatable written above code.
but it is not filling properly.
"Datatable Wrongly Filled"
FacilityID:12787
FacilityName:ACME Medical Center
FacilityLocation:XYZ
FacilityID:27875
FacilityName:Medical Center
FacilityLocation:kh
How should i modify the code the datatable should be filled like below
FacilityID FacilityName FacilityLocation
12787 ACME Medical Center XYZ
27875 Medical Center kh
Some stuff which is already available on net may be helpful to you
please go through these links:
http://www.codeproject.com/KB/database/ReadTextFile.aspx
http://aspalliance.com/1107_CodeSnip_Reading_CSV_Files_Using_Dataset.all
http://www.c-sharpcorner.com/UploadFile/mgold/ConnectODBCText11262005070206AM/ConnectODBCText.aspx
private string GetID(string str)
{
if (!string.IsNullOrEmpty(str.Split(':')[1]))
{
return str.Split(':')[1].Replace("FacilityName", string.Empty);
}
return string.Empty;
}
private string GetName(string str)
{
if (!string.IsNullOrEmpty(str.Split(':')[2]))
{
return str.Split(':')[2].Replace("FacilityLocation", string.Empty);
}
return string.Empty;
}
private string GetLocation(string str)
{
if (!string.IsNullOrEmpty(str.Split(':')[3]))
{
return str.Split(':')[3];
}
return string.Empty;
}
private string Button Click()
{
string rows = "FacilityID:12787 FacilityName:ACME Medical Center FacilityLocation:XYZ";
DataTable tbl = new DataTable("test");
if (rows.Length != 0)
{
tbl.Columns.Add("FacilityID");
tbl.Columns.Add("FacilityName");
tbl.Columns.Add("FacilityLocation");
var newRow = tbl.NewRow();
newRow[0] = GetID(rows);
newRow[1] = GetName(rows);
newRow[2] = GetLocation(rows);
tbl.Rows.Add(newRow);
dataGridView1.DataSource = tbl.DefaultView;
}
}

OnSelectedIndexChanged of asp.net DropDownList which is outside datalist

I have a DataList that contains CheckBoxList, and I filter the datalist on selectedindexchanged outside datalist. The problem is when I select value from dropdownlist I can't get the checked values from database
and checkboxlist items count is 0
this is the code
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
string GroupValue;
if (DropDownList1.SelectedValue.ToString().IsEmpty()) { GroupValue = null; } else { GroupValue = DropDownList1.SelectedValue.ToString(); }
if (pageMode == PageMode.Update)
{
int rowID = int.Parse(GrdUsers.GetRowValues(GrdUsers.FocusedRowIndex, "ID").ToString());
//ConnectionLayer cn = new ConnectionLayer();
//DataTable dt = cn.ExecutQuery("PagesSys", new object[] { 0, DropDownList1.SelectedItem.Text.ToString() });
//dlstPages.DataSource = dt;
//dlstPages.DataBind();
BindOption(rowID);
}
private void BindOption(int UserID)
{
try
{
if (pageMode == PageMode.Update)
{
if (DropDownList1.SelectedItem.Value != "-1")
{
dlstPages.DataSource = ViewState["FunctionOption"];
dlstPages.DataBind();
if (dlstPages.Items.Count > 0)
{
for (int i = 0; i < dlstPages.Items.Count; i++)
{
DataTable dt = new Users().UserPrivilege(UserID, int.Parse(dlstPages.DataKeys[i].ToString()));
if (dt.Rows.Count > 0)
{
dt.PrimaryKey = new DataColumn[] { dt.Columns["OptionId"] };
CheckBoxList chklist = (CheckBoxList)dlstPages.Items[i].FindControl("chkOption");
for (int j = 0; j < chklist.Items.Count; j++)
{
if (dt.Rows.Find(chklist.Items[j].Value) != null)
{
chklist.Items[j].Selected = true;
}
}
}
}
}
}
}
}
catch (Exception ex)
{
}
}
You need to use the arguments to the function to get the dropdown list object, then you can find the selected value. Something like:
DropDownList ddl= (DropDownList)sender;
var value = ddl.SelectedValue.ToString();

How to Update DataTable in C# without For Each Loop?

I'm trying to run loop for each row in my data table but its giving me error as I can't modify a collection in for each loop ... what else can i do to update table?
I am trying to remove duplicate entries w.r.t single column that is appliance name and if such selection is made based on duplicate appliance name then simply update the old quantity.
Here is the code:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
dt = new DataTable();
dt.Columns.Add("Appliance Name", typeof(string));
dt.Columns.Add("Quantity", typeof(int));
dt.Columns.Add("Day Time(Hrs)", typeof(int));
dt.Columns.Add("Backup Time(Hrs)", typeof(int));
// dt.Rows.Add("Sana", 5, 4, 3);
Session["MyDataTable"] = dt;
}
}
protected void BtnAddNext_Click(object sender, EventArgs e)
{
DataTable dtab = (DataTable)Session["MyDataTable"];
if (dtab.Rows.Count != 0)
{
foreach (DataRow r in dtab.Rows)
{
if (Convert.ToString(r["Appliance Name"]) == DDLAppName.Text)
{
int temp = Convert.ToInt32(r["Quantity"]);
r["Quantity"] = Convert.ToInt32(QtyTB.Text) + temp;
}
else
{
dtab.Rows.Add(DDLAppName.SelectedValue, Convert.ToInt32(QtyTB.Text), Convert.ToInt32(DayTymTB.Text), Convert.ToInt32(BackUpTymTB.Text));
}
}
}
else if (dtab.Rows.Count == 0)
{
dtab.Rows.Add(DDLAppName.SelectedValue, Convert.ToInt32(QtyTB.Text), Convert.ToInt32(DayTymTB.Text), Convert.ToInt32(BackUpTymTB.Text));
}
//dtab = dtab.DefaultView.ToTable(true, "Appliance Name", "Quantity", "Day Time(Hrs)", "Backup Time(Hrs)");
AllItems.DataSource = dtab;
AllItems.DataBind();
AllItems.Visible = true;
}
Simply try using for loop instead of foreach like this:
for (int rowIndex = 0; rowIndex < dtab.Rows.Count; rowIndex++)
{
DataRow r = dtab.Rows[rowIndex];
if (Convert.ToString(r["Appliance Name"]) == DDLAppName.Text)
{
int temp = Convert.ToInt32(r["Quantity"]);
r["Quantity"] = Convert.ToInt32(QtyTB.Text) + temp;
}
else
{
dtab.Rows.Add(DDLAppName.SelectedValue, Convert.ToInt32(QtyTB.Text), Convert.ToInt32(DayTymTB.Text), Convert.ToInt32(BackUpTymTB.Text));
}
}
EDIT 1:
The foreach statement is used to iterate through the collection to get the information that you want, but can not be used to add or remove items from the source collection to avoid unpredictable side effects. If you need to add or remove items from the source collection, use a for loop. (From MSDN)
Edit 2
If you wanna add rows in your foreach loop, do as follows:
DataRow[] dataRows = new DataRow[dt.Rows.Count];
dt.Rows.CopyTo(dataRows, 0);
foreach (DataRow r in dataRows)
{
...
}

Adding Child Nodes to a Treeview from DataTable (C# Windows Forms)

I'm having a hard time trying to get a Treeview to display child notes.
I have a DataTable which is filled with Data from a query.
The table is something like this.
| ParentOT | ChildOT
-------------------
1 | 2
1 | 3
1 | 4
4 | 5
5 | 6
now, what I need is to order this data in a TreeView.
The result must be something like this (using this same table)
1
|
--2
|
--3
|
--4
|
--5
|
--6
I tried to this on Windows Forms and the only thing I can get is the tree to show only 1 set of childs. like this
1
|
--2
|
--3
|
--4
|
--5
|
5
|
--6
I tried to do it like this:
DataTable arbolSub = mssql_cnn.ejecutarSqlSelect(q2);
//Metodo 2: muestra las ot correctamente pero no muestra mas detalle de subOT.
if (trvOTHs.Nodes.Count > 0)
{
trvOTHs.Nodes.Clear();
}
trvOTHs.BeginUpdate();
if (arb.Rows.Count > 0)
{
string otPadre = arb.Rows[0][0].ToString();
int nivel = 0;
trvOTHs.Nodes.Add(arbolSub.Rows[0]["OT Padre"].ToString());
for (int i = 0; i < arbolSub.Rows.Count; i++)
{
//trvOTHs.Nodes.Add(arbolSub.Rows[0]["OT Padre"].ToString());
if (arbolSub.Rows[i]["OT Padre"].ToString() == otPadre)
{
if (trvOTHs.Nodes[nivel].Text == otPadre)
{
trvOTHs.Nodes[nivel].Nodes.Add(arbolSub.Rows[i]["OT Hija"].ToString());
}
}
else
{
otPadre = arbolSub.Rows[i+1]["OT Padre"].ToString();
TreeNode nodo = new TreeNode(otPadre.ToString());
trvOTHs.Nodes.Add(nodo);
nivel++;
}
}
trvOTHs.Nodes[0].Remove();
trvOTHs.ExpandAll();
}
trvOTHs.EndUpdate();
where trvOTHs is a TreeView.
Please Help! Thanks
EDIT: Thanks for the reply. I finally worked around this,using a idea given by a friend and using something like the suggested solution by #Mohammad abumazen.
I ended up using two methods recursively:
private TreeView cargarOtPadres(TreeView trv, int otPadre, DataTable datos)
{
if (datos.Rows.Count > 0)
{
foreach (DataRow dr in datos.Select("OTPadre='"+ otPadre+"'"))
{
TreeNode nodoPadre = new TreeNode();
nodoPadre.Text = dr["OTPadre"].ToString();
trv.Nodes.Add(nodoPadre);
cargarSubOts(ref nodoPadre, int.Parse(dr["OTHija"].ToString()), datos);
}
}
return trv;
}
private void cargarSubOts(ref TreeNode nodoPadre, int otPadre, DataTable datos)
{
DataRow[] otHijas = datos.Select("OTPadre='" + otPadre +"'");
foreach (DataRow drow in otHijas)
{
TreeNode hija = new TreeNode();
hija.Text = drow["OTHija"].ToString();
nodoPadre.Nodes.Add(hija);
cargarSubOts(ref hija, int.Parse(drow["OTHija"].ToString()), datos);
}
}
This did it. I leave it here in case anyone needs it. Thanks again.
The main issue in your code that you are not looking for the child parent in the tree view to add it under , you add them all under main parent.
i made some changes to your code hopefully it work straight forward or with minor changes at your side:
if (arb.Rows.Count > 0)
{
TreeNode MainNode = new TreeNode();
string otPadre = arb.Rows[0][0].ToString();
int nivel = 0;
MainNode.Text = otPadre;
trvOTHs.Nodes.Add(MainNode);
for (int i = 0; i < arbolSub.Rows.Count; i++)
{
TreeNode child = new TreeNode();
child.Text = row["OT Hija"].ToString();
if (arbolSub.Rows[i]["OT Padre"].ToString() == otPadre)
{
MainNode.Nodes.Add(child);
}
else
{
FindParent(MainNode, row["OT Padre"].ToString(), child);
}
}
trvOTHs.ExpandAll();
}
this function to find the parent node :
private void FindParent(TreeNode ParentNode, string Parent, TreeNode ChildNode)
{
foreach (TreeNode node in ParentNode.Nodes)
{
if (node.Text.ToString() == Parent)
{
node.Nodes.Add(ChildNode);
}
else
{
FindParent(node, Parent, ChildNode);
}
}
}
I would do something like this, You should consider using Dictionary and HashSet for maximum performance:
//use this extension method for convenience
public static class TreeViewExtension {
public static void LoadFromDataTable(this TreeView tv, DataTable dt){
var parentNodes = dt.AsEnumerable()
.GroupBy(row => (string)row[0])
.ToDictionary(g=> g.Key, value=> value.Select(x=> (string)x[1]));
Stack<KeyValuePair<TreeNode,IEnumerable<string>>> lookIn = new Stack<KeyValuePair<TreeNode,IEnumerable<string>>>();
HashSet<string> removedKeys = new HashSet<string>();
foreach (var node in parentNodes) {
if (removedKeys.Contains(node.Key)) continue;
TreeNode tNode = new TreeNode(node.Key);
lookIn.Push(new KeyValuePair<TreeNode,IEnumerable<string>>(tNode,node.Value));
while (lookIn.Count > 0) {
var nodes = lookIn.Pop();
foreach (var n in nodes.Value) {
IEnumerable<string> children;
TreeNode childNode = new TreeNode(n);
nodes.Key.Nodes.Add(childNode);
if (parentNodes.TryGetValue(n, out children)) {
lookIn.Push(new KeyValuePair<TreeNode,IEnumerable<string>>(childNode,children));
removedKeys.Add(n);
}
}
}
tv.Nodes.Add(tNode);
}
}
}
//usage
treeView1.LoadFromDataTable(yourDataTable);
NOTE the input DataTable should contain data as you posted in your question. There is no need for other kinds of Sub-DataTable.
Thanks for the reply. I finally worked around this,using a idea given by a friend and using something like the suggested solution by #Mohammad abumazen.
I ended up using two methods recursively:
private TreeView cargarOtPadres(TreeView trv, int otPadre, DataTable datos)
{
if (datos.Rows.Count > 0)
{
foreach (DataRow dr in datos.Select("OTPadre='"+ otPadre+"'"))
{
TreeNode nodoPadre = new TreeNode();
nodoPadre.Text = dr["OTPadre"].ToString();
trv.Nodes.Add(nodoPadre);
cargarSubOts(ref nodoPadre, int.Parse(dr["OTHija"].ToString()), datos);
}
}
return trv;
}
private void cargarSubOts(ref TreeNode nodoPadre, int otPadre, DataTable datos)
{
DataRow[] otHijas = datos.Select("OTPadre='" + otPadre +"'");
foreach (DataRow drow in otHijas)
{
TreeNode hija = new TreeNode();
hija.Text = drow["OTHija"].ToString();
nodoPadre.Nodes.Add(hija);
cargarSubOts(ref hija, int.Parse(drow["OTHija"].ToString()), datos);
}
}
This did it. I leave it here in case anyone needs it. Thanks again.

how to get checkboxlist values to be selected and be displayed

I binded my checkboxlist by:
string countrySQL = "Select id, CurrencyName From VirtualAccount_Currency";
string[] param = { };
object[] paramVal = { };
return ClassDBQuery.ExecDataReader(countrySQL, param, paramVal);
datalayer:
string selCurrSQL = "SELECT * FROM VirtualAccount WHERE MerchantMasterID = #id";
string[] param = { "#id" };
object[] paramVal = { currID };
return ClassDBQuery.ExecDataReader(selCurrSQL, param, paramVal);
here is my code:
DataTable currDT = new DataTable();
currDT = ClassView.SelectCurrency(idses);
foreach (DataRow row in currDT.Rows)
{
foreach (ListItem item in currencyBox.Items)
{
if (item.Value == (row["CurrencyID"].ToString()))
{
item.Selected = true;
break;
}
}
}
Now, when i run my code, there is no error encountered but the values of the checkbox are displayed. When I am debugging it, the system only loops in the first foreach the enters the second foreach but doesn't go through the if statement...
What's wrong with my code..?
thank you...
try below,
foreach (DataRow row in currDT.Rows)
{
foreach (ListItem item in currencyBox.Items)
{
// check here what you get
int currencyId= row.Field<int>("CurrencyID");
if (item.Value == currencyId.ToString())
{
item.Selected = true;
break;
}
}
}
if your field CurrencyID can have null values then,
int? currencyId= row.Field<int?>("CurrencyID");
if (currencyId! =null && item.Value == currencyId.ToString())
{
item.Selected = true;
break;
}
Try This:-
for (int j = 0; j < CheckBoxList1.Items.Count; j++)
{
if (CheckBoxList1.Items[j].Text.Trim() ==row["CurrencyID"].ToString())
{
CheckBoxList1.Items[j].Selected = true; break;
}
}
Hope this helps!!

Categories