i build application and add files to my ListView, I want the last file added each time will emphasize so inside my Foreach statement i added lvFiles.Items[lvFiles.Items.Count - 1].Selected = true; but in this case all the files inside my ListView emphasized and not only the last one
List<string> filesList
foreach (string fileName in filesList)
{
FileInfo fileInfo = new FileInfo(fileName);
if (checkFileCreationDate(fileInfo))
{
if (editcap.isWiresharkFormat(fileInfo.FullName))
{
if (editcap.isLibpcapFormat(fileInfo.FullName))
{
addFileToListBox(fileInfo.FullName, capinfos.getFileDuration(fileInfo.FullName));
}
else if (!editcap.isLibpcapFormat(fileInfo.FullName))
{
fileToAdd = editcap.getNewFileName(fileInfo.FullName);
if (new FileInfo(fileToAdd).Exists && !fileInfo.Exists)
{
addFileToListBox(fileToAdd, capinfos.getFileDuration(fileInfo.FullName));
}
}
}
}
}
private void addFileToListBox(string filePath, string duration)
{
item = new ListViewItem(new string[] { new FileInfo(filePath).Name, duration, "Waiting" });
item.Tag = new FileInfo(filePath).FullName;
}
just put that statement after your foreach and it should work.
like:
foreach(var x in colY)
{
//check file
lvFiles.Items[lvFiles.Items.Count - 1].Selected = false;
//add item here
lvFiles.Items[lvFiles.Items.Count - 1].Selected = true;
}
You need to start by unselecting the previous elements and only then selecting the final one:
foreach (var item in lvFiles.Items)
{
item.Selected = false;
}
lvFiles.Items[lvFiles.Items.Count - 1].Selected = true;
Related
private void Bgw_DoWork(object sender, DoWorkEventArgs e)
{
fileslist = GetFiles(textBoxFileDirectory.Text, "*.*", fsw.IncludeSubdirectories).ToList();
if (bgw.CancellationPending == true)
{
e.Cancel = true;
return;
}
if (fileslist.Count > 0)
{
bgw.ReportProgress(fileslist.Count);
for (int i = 0; i < fileslist.Count; i++)
{
if (bgw.CancellationPending == true)
{
e.Cancel = true;
return;
}
FileInfo info = new FileInfo(fileslist[i]);
if (File.Exists(info.FullName))
{
dic.Add(fileslist[i], info.Length);
}
}
}
}
until now i used to make :
fileslist = GetFiles(#"D:\", "*.*", fsw.IncludeSubdirectories).ToList();
but now i wan to use the text inside the textBoxFileDirectory control the problem is that you can't use ui inside the dowork event.
I tried this :
textBoxFileDirectory.Dispatcher.Invoke(DispatcherPriority.Normal,
new Action(() => { fileslist = GetFiles(textBoxFileDirectory.Text, "*.*", fsw.IncludeSubdirectories).ToList(); }));
but this make the whole application to freeze and then to continue working when getting files from drive D but it's freezing when getting the files.
but when trying to get the files this way from C drive it's also freezing but after some time i'm getting this message :
This is the GetFiles method :
public static IEnumerable<string> GetFiles(string root, string searchPattern, bool includeSubDirectories)
{
Stack<string> pending = new Stack<string>();
pending.Push(root);
while (pending.Count != 0)
{
var path = pending.Pop();
string[] next = null;
try
{
next = Directory.GetFiles(path, searchPattern);
}
catch { }
if (next != null && next.Length != 0)
foreach (var file in next) yield return file;
try
{
if (includeSubDirectories)
{
next = Directory.GetDirectories(path);
foreach (var subdir in next) pending.Push(subdir);
}
}
catch { }
}
}
So I have a button, where if you click it, it adds "Candy" to a listbox, how do I make it so, if another item with the same name is being added, instead of adding it in a new line, update the first line to show x2, 3, 4, etc. Is that possible or would I have to make another Listbox and match the index? I've tried the following with another listbox and an int variable.
private void btnCandy_Click(object sender, EventArgs e)
{
lstProducts.Items.Add("Candy");
foreach (var item in lstProducts.Items)
{
if (item.ToString() == "Candy")
{
++Productcount;
lstQuantity.Items.Add(Productcount);
if (Productcount > 1)
{
lstQuantity.Items.Insert(lstProducts.Items.IndexOf("Candy"), Productcount);
}
}
}
}
using System.Text.RegularExpressions;
Use:
private void btnCandy_Click(object sender, EventArgs e)
{
string query = "Candy";
bool isExist = false;
for (int i = 0; i < lstProducts.Items.Count; i++)
{
var s = lstProducts.Items[i].ToString();
if (s.StartsWith(query))
{
if (s == query)
{
lstProducts.Items[i] = query + "x2";
isExist = true;
break;
}
else
{
// Escape your plain text before use with regex
var pattern = Regex.Escape(query);
// Check if s has this formnat: queryx2, queryx3, queryx4, ...
Match m = Regex.Match(s, "^" + pattern + #"x(\d+)$");
if (m.Success)
{
lstProducts.Items[i] = query + "x" + (Int32.Parse(m.Groups[1].Value) + 1);
isExist = true;
break;
}
}
}
}
if (!isExist) lstProducts.Items.Add(query);
}
Note:
\d mean any digit (0 - 9)
I'd try to iterate through listbox items and if I find "Candy" then take that index and update title.
private void btnCandy_Click(object sender, EventArgs e)
{
bool found = false;
foreach (var item in lstProducts.Items)
{
if (item.ToString().StartsWith("Candy"))
{
// update item title
found = true;
break; // no need to continue
}
}
if(!found)
{
lstProducts.Items.Add("Candy");
}
}
this way you are not going to add duplicates
Here is some pseudo-code to help you. Add this to your button click event:
int i = 0;
foreach (string item in listbox1.Items)
{
If (item == textbox1.text) //textbox1.text contains the string such as 'candy'
{
i++;
listbox1.Items.Remove(item);
listbox1.Items.Add(textbox1.text + " " + i.ToString());
}
}
You may have to reset the counter as needed.
Hello folks I am trying to update the quantity of a product that is being ordered. If the product already exists in the users 'basket' instead of inserting a new row, the quantity in the row with the existing item should be updated. It is updating but a new row is also inserted with the quantity that should have been added to the original row, like so:
I'm guessing something is wrong logically in my code but, I can't spot it.
private void btn_add_Click(object sender, EventArgs e)
{
try
{
ListViewItem item = new ListViewItem(list_Select_Product.SelectedItems[0].Text);
item.SubItems.Add(list_Select_Product.SelectedItems[0].SubItems[1].Text);
item.SubItems.Add(txt_quantity.Text);
bool ok = true;
if (!validNumbers(txt_quantity))
ok = false;
if (!validLength(txt_quantity, 1, 2))
ok = false;
if (ok == true)
{
foreach (ListViewItem lvi in list_view_orderitems.Items)
{
if(lvi.SubItems[0].Text == list_Select_Product.SelectedItems[0].Text)
{
int UpdateQunat = Convert.ToInt32(lvi.SubItems[2].Text);
int AddMe = Convert.ToInt32(txt_quantity.Text);
UpdateQunat = UpdateQunat + AddMe;
lvi.SubItems[2].Text = Convert.ToString(UpdateQunat);
list_view_orderitems.Items.Add(item);
}
else if (lvi.SubItems[0].Text != list_Select_Product.SelectedItems[0].Text)
{
list_view_orderitems.Items.Add(item);
}
}
if(list_view_orderitems.Items.Count == 0)
{
list_view_orderitems.Items.Add(item);
}
}
}
catch
{
MessageBox.Show("A product must be selected");
}
}
Look a little closer in the foreach loop. You actually add it there as well. (So you should remove that)
foreach (ListViewItem lvi in list_view_orderitems.Items)
{
if(lvi.SubItems[0].Text == list_Select_Product.SelectedItems[0].Text)
{
int UpdateQunat = Convert.ToInt32(lvi.SubItems[2].Text);
int AddMe = Convert.ToInt32(txt_quantity.Text);
UpdateQunat = UpdateQunat + AddMe;
lvi.SubItems[2].Text = Convert.ToString(UpdateQunat);
// adding it again. This line is not needed.
list_view_orderitems.Items.Add(item);
}
else if (lvi.SubItems[0].Text != list_Select_Product.SelectedItems[0].Text)
{
list_view_orderitems.Items.Add(item);
}
}
I this that it this if you need to get rid of the item.Add (i marked it:
if(lvi.SubItems[0].Text == list_Select_Product.SelectedItems[0].Text)
{
int UpdateQunat = Convert.ToInt32(lvi.SubItems[2].Text);
int AddMe = Convert.ToInt32(txt_quantity.Text);
UpdateQunat = UpdateQunat + AddMe;
lvi.SubItems[2].Text = Convert.ToString(UpdateQunat);
// list_view_orderitems.Items.Add(item);
}
I have a CheckedListBox that has X number of items. These items are placed there at runtime. These items are supposed to represent reports that can be displayed in the DataGridView. What I need to do now is display the record count for each report in parenthesis right next to the report name. I tried, not for too long, to edit the actual name of the item but couldn't find out how to do it. So then, I brute forced it. Saved the items to an array, cleared the items, appended the record counts to each item in the array, created new items. Well, this has caused issues because now it's not retaining my checks and the reason why is because whenever I generate the reports, I clear the items and recreate them. Well, rather than doing another foreach loop to save the checked status, does anyone know of a way to change the text of existing items in a CheckedListBox?
Here is the code I currently have:
In the MainForm.Designer.cs:
this.clbReports.Items.AddRange(new object[] {
"Report 1",
"Report 2",
"Report 3",
"Report 4",
"Report 5",
"Report 6",
"Report 7",
"Report 8",
"Report 9",
"Report 10",
"Report 11"});
And it looks like:
And I want it to look like (but there won't all be 0's):
Here is the SelectedIndexChanged function:
private void clbReports_SelectedIndexChanged(object sender, EventArgs e)
{
string strCheckBox = clbReports.SelectedItem.ToString();
bool bShowAllIsChecked = clbReports.GetItemChecked(clbReports.FindString("Show All Error Reports"));
bool bSelected = clbReports.GetItemChecked(clbReports.FindString(strCheckBox));
int nIndex = -1;
if (strCheckBox.Contains("Show All Error Reports"))
{
foreach (string str in _strReports)
{
if (!str.Contains("Show All Error Reports") && !str.Contains("Show Tagged Records"))
{
nIndex = clbReports.FindString(str);
if (nIndex > -1)
{
clbReports.SetItemChecked(nIndex, bSelected);
}
}
}
}
else
{
if (strCheckBox.Contains("Show All Error Reports") || bShowAllIsChecked)
{
foreach (string str in _strReports)
{
nIndex = clbReports.FindString(str);
if (nIndex > -1)
{
clbReports.SetItemChecked(nIndex, false);
}
}
}
nIndex = clbReports.FindString(strCheckBox);
if (nIndex > -1)
{
clbReports.SetItemChecked(nIndex, bShowAllIsChecked ? true : bSelected);
}
}
string[] strCheckedItems = new string[clbReports.CheckedItems.Count];
clbReports.CheckedItems.CopyTo(strCheckedItems, 0);
List<string> checkBoxReportFilter = new List<string>();
foreach (ReportRecord obj in this._lstReportRecords)
{
foreach (string str in strCheckedItems)
{
if (str.Contains(obj.Description))
{
checkBoxReportFilter.Add(obj.PartID.ToString());
}
}
}
try
{
if (checkBoxReportFilter.Count == 0 && clbReports.CheckedItems.Count > 0)
{
throw new NullReferenceException();
}
_strReportFilter = String.Join(",", checkBoxReportFilter.ToArray());
}
catch (NullReferenceException)
{
_strReportFilter = "-1";
}
generateReport();
}
And here is the code where I am clearing the items, getting the report counts and creating the new items.
_lstReportRecords = _dataController.ReportList;
bool[] bChecked = new bool[clbReports.Items.Count];
int nCounter = 0;
foreach (string str in _strReports)
{
foreach (string str2 in clbReports.SelectedItems)
{
bChecked[nCounter] = str2.Contains(str);
}
nCounter++;
}
clbReports.Items.Clear();
nCounter = 0;
foreach (string str in _strReports)
{
int nCount = _lstReportRecords.Where<ReportRecord>(delegate(ReportRecord rr) {
return rr.Description == str;
}).Count();
string newReport = str + " (" + nCount + ")";
clbReports.Items.Add(newReport);
clbReports.SetItemChecked(nCounter, bChecked[nCounter]);
nCounter++;
}
Please tell me there is an easier way to do this. I tried doing foreach loops through the clbReports.Items but it wants me to cast it to a string (errored on me when trying to cast to a CheckBox) so I couldn't change the value. And even if I could cast it to a CheckBox, I have a feeling it will give me the error that Enumeration has failed because the list has been changed (or however they word it). Any and all help is welcome. Thanks.
Edit: Please know that the Report X are just so that the actual report names aren't displayed to keep it generic. However, in the code, I just copied and pasted so the Show All Error Reports and Show All Tagged Records are reports I need to check.
The right ( == most simple and most direct) answer and solution is:
this.clbReports.Items[nIndex] = "new text of the item"
yes, those items are of type "object". No, nobody minds that, string is an object too ;)
If I were you, I'd try to give the INotifyPropertyChanged Interface a go.
You Shouldn't mess with events unless necessary. this will mean you can't use the designer to create the items, but as far as I've understood, it's a runtime-modified list anyway...
In detail:
• Create A Class (e.g.'Foo') that Implements INotifyPropertyChanged (Basically this will tell any listener that the text property has changed). This class will hold the names of all entries.
• create an ObservableCollection and bind your CheckedListBox to that Collection. In WinForms you will have to create a DataBindingSource and plug your Collection to one end and the ComboBox to the other end.
• Any change made to the collection will be visible in the control.
HTH
Sebi
In order to change the items in a ListBox (or a CheckedListBox), you should change these items' ToString() result.
The easiest solution would be to create a "Holder" class, which has a reference to the report it represents. Then the Holder class' ToString() method should be something like this:
public override string ToString()
{
return String.Format("{0} ({1})", BaseStr, MyReport.RecordCount);
}
If you change MyReport.RecordCount somehow (because a report's record count changes), you can just call clbReports.Refresh(), and it'll automatically show the new value.
I think this way you don't even need the temporary array solution in the second code block; however, I'd like to suggest an alternative way of getting the item's checked state.
You can iterate through the clbReports.CheckedIndices, and fill your bChecked array with true values only for indices in that array.
Well, due to time constraints I tried something else. I went with a ListView where CheckBoxes = true and View = List. I also removed Show All Error Reports and Show Tagged Records to checkboxes outside of the list. This made it a lot easier to do the functions I wanted. Here is the new code.
MainForm.Designer.cs
//
// cbTaggedRecords
//
this.cbTaggedRecords.AutoSize = true;
this.cbTaggedRecords.Location = new System.Drawing.Point(151, 9);
this.cbTaggedRecords.Name = "cbTaggedRecords";
this.cbTaggedRecords.Size = new System.Drawing.Size(106, 17);
this.cbTaggedRecords.TabIndex = 3;
this.cbTaggedRecords.Text = "Tagged Records";
this.cbTaggedRecords.UseVisualStyleBackColor = true;
this.cbTaggedRecords.CheckedChanged += new System.EventHandler(this.ShowTaggedRecords_CheckChanged);
//
// cbAllErrorReports
//
this.cbAllErrorReports.AutoSize = true;
this.cbAllErrorReports.Location = new System.Drawing.Point(6, 9);
this.cbAllErrorReports.Name = "cbAllErrorReports";
this.cbAllErrorReports.Size = new System.Drawing.Size(102, 17);
this.cbAllErrorReports.TabIndex = 2;
this.cbAllErrorReports.Text = "All Error Reports";
this.cbAllErrorReports.UseVisualStyleBackColor = true;
this.cbAllErrorReports.CheckedChanged += new System.EventHandler(this.ShowAllErrorReports_CheckChanged);
//
// listView1
//
this.listView1.CheckBoxes = true;
listViewItem1.StateImageIndex = 0;
listViewItem2.StateImageIndex = 0;
listViewItem3.StateImageIndex = 0;
listViewItem4.StateImageIndex = 0;
listViewItem5.StateImageIndex = 0;
listViewItem6.StateImageIndex = 0;
listViewItem7.StateImageIndex = 0;
listViewItem8.StateImageIndex = 0;
listViewItem9.StateImageIndex = 0;
this.listView1.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
listViewItem1,
listViewItem2,
listViewItem3,
listViewItem4,
listViewItem5,
listViewItem6,
listViewItem7,
listViewItem8,
listViewItem9});
this.listView1.Location = new System.Drawing.Point(6, 29);
this.listView1.Name = "listView1";
this.listView1.Size = new System.Drawing.Size(281, 295);
this.listView1.TabIndex = 1;
this.listView1.UseCompatibleStateImageBehavior = false;
this.listView1.View = System.Windows.Forms.View.List;
this.listView1.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.listView_ItemChecked);
MainForm.cs
private void listView_ItemChecked(object sender, ItemCheckedEventArgs e)
{
if (e != null)
{
int nLength = e.Item.Text.IndexOf("(") - 1;
string strReport = nLength <= 0 ? e.Item.Text : e.Item.Text.Substring(0, nLength);
if (e.Item.Checked)
{
_lstReportFilter.Add(strReport);
}
else
{
_lstReportFilter.Remove(strReport);
}
}
List<string> checkBoxReportFilter = new List<string>();
foreach (ReportRecord obj in this._lstReportRecords)
{
foreach (string str in _lstReportFilter)
{
if (str.ToLower().Contains(obj.Description.ToLower()))
{
checkBoxReportFilter.Add(obj.PartID.ToString());
}
}
}
try
{
if (checkBoxReportFilter.Count == 0 && listView1.CheckedItems.Count > 0)
{
throw new NullReferenceException();
}
_strReportFilter = String.Join(",", checkBoxReportFilter.ToArray());
}
catch (NullReferenceException)
{
_strReportFilter = "-1";
}
if (!bShowAll)
{
generateReport();
}
}
private void ShowAllErrorReports_CheckChanged(object sender, EventArgs e)
{
bShowAll = true;
foreach (ListViewItem lvi in listView1.Items)
{
lvi.Checked = ((CheckBox)sender).Checked;
}
_lstReportFilter.Clear();
bShowAll = false;
generateReport();
}
private void ShowTaggedRecords_CheckChanged(object sender, EventArgs e)
{
bool bChecked = ((CheckBox)sender).Checked;
if (bChecked)
{
if (!_lstReportFilter.Contains("Show Tagged Records"))
{
_lstReportFilter.Add("Show Tagged Records");
}
}
else
{
_lstReportFilter.Remove("Show Tagged Records");
}
listView_ItemChecked(null, null);
}
Code to add counts to CheckBoxes
_lstReportRecords = _dataController.ReportList;
int nTotalCount = 0;
foreach (ListViewItem lvi in listView1.Items)
{
int nCount = _lstReportRecords.Where(rr => lvi.Text.Contains(rr.Description)).Count();
nTotalCount += nCount;
lvi.Text = (lvi.Text.Contains("(") ? lvi.Text.Substring(0, lvi.Text.IndexOf("(") + 1) : lvi.Text + " (") + nCount.ToString() + ")";
}
cbAllErrorReports.Text = (cbAllErrorReports.Text.Contains("(") ? cbAllErrorReports.Text.Substring(0, cbAllErrorReports.Text.IndexOf("(") + 1) : cbAllErrorReports.Text + " (") + nTotalCount.ToString() + ")";
int nTaggedCount = _lstReportRecords.Where(rr => rr.Description.Contains("Tagged")).Count();
cbTaggedRecords.Text = (cbTaggedRecords.Text.Contains("(") ? cbTaggedRecords.Text.Substring(0, cbTaggedRecords.Text.IndexOf("(") + 1) : cbTaggedRecords.Text + " (") + nTaggedCount.ToString() + ")";
Thank you all for your help and ideas.
I'm trying to populate a treeview from a list of folder path, for example:
C:\WINDOWS\addins
C:\WINDOWS\AppPatch
C:\WINDOWS\AppPatch\MUI
C:\WINDOWS\AppPatch\MUI\040C
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI\0409
with an ouput like this:
├───addins
├───AppPatch
│ └───MUI
│ └───040C
├───Microsoft.NET
│ └───Framework
│ └───v2.0.50727
│ └───MUI
│ └───0409
Notice there's no 'C:\WINDOWS\Microsoft.NET' or 'C:\WINDOWS\Microsoft.NET\Framework' in the list. I've been working on this for almost two days and there's a bunch of bug in my code. Hope I can get help from here.
Thanks.
Eric
private void Form1_Load(object sender, EventArgs e)
{
var paths = new List<string>
{
#"C:\WINDOWS\AppPatch\MUI\040C",
#"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727",
#"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI",
#"C:\WINDOWS\addins",
#"C:\WINDOWS\AppPatch",
#"C:\WINDOWS\AppPatch\MUI",
#"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI\0409"
};
treeView1.PathSeparator = #"\";
PopulateTreeView(treeView1, paths, '\\');
}
private static void PopulateTreeView(TreeView treeView, IEnumerable<string> paths, char pathSeparator)
{
TreeNode lastNode = null;
string subPathAgg;
foreach (string path in paths)
{
subPathAgg = string.Empty;
foreach (string subPath in path.Split(pathSeparator))
{
subPathAgg += subPath + pathSeparator;
TreeNode[] nodes = treeView.Nodes.Find(subPathAgg, true);
if (nodes.Length == 0)
if (lastNode == null)
lastNode = treeView.Nodes.Add(subPathAgg, subPath);
else
lastNode = lastNode.Nodes.Add(subPathAgg, subPath);
else
lastNode = nodes[0];
}
}
}
for a linq'y version:
public static TreeNode MakeTreeFromPaths(List<string> paths, string rootNodeName = "", char separator = '/')
{
var rootNode = new TreeNode(rootNodeName);
foreach (var path in paths.Where(x => !string.IsNullOrEmpty(x.Trim()))) {
var currentNode = rootNode;
var pathItems = path.Split(separator);
foreach (var item in pathItems) {
var tmp = currentNode.Nodes.Cast<TreeNode>().Where(x => x.Text.Equals(item));
currentNode = tmp.Count() > 0 ? tmp.Single() : currentNode.Nodes.Add(item);
}
}
return rootNode;
}
ehosca answer is correcr, but there is a little problem,
when I change paths to like this
C:\WINDOWS\AppPatch\MUI\040C
D:\WIS\Microsoft.NET\Framework\v2.0.50727
E:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI
C:\WINDOWS\addins
C:\WINDOWS\AppPatch
C:\WINDOWS\AppPatch\MUI
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI\0409
It will popoulate treeview like this.
But adding some extra code we can avoid this situation. So I changed the code in PopulateTreeView
private static void PopulateTreeView(TreeView treeView, string[] paths, char pathSeparator)
{
TreeNode lastNode = null;
string subPathAgg;
foreach (string path in paths)
{
subPathAgg = string.Empty;
foreach (string subPath in path.Split(pathSeparator))
{
subPathAgg += subPath + pathSeparator;
TreeNode[] nodes = treeView.Nodes.Find(subPathAgg, true);
if (nodes.Length == 0)
if (lastNode == null)
lastNode = treeView.Nodes.Add(subPathAgg, subPath);
else
lastNode = lastNode.Nodes.Add(subPathAgg, subPath);
else
lastNode = nodes[0];
}
lastNode = null; // This is the place code was changed
}
}
Now it works fine like this
I took your code, and it work very well,
but i made just a little modification for improving the load speed
when it is used whit a large list of files
it seems like find operation, and string operations generally are very slow
private TreeNode PopulateTreeNode2(string[] paths, string pathSeparator)
{
if (paths == null)
return null;
TreeNode thisnode = new TreeNode();
TreeNode currentnode;
char[] cachedpathseparator = pathSeparator.ToCharArray();
foreach (string path in paths) {
currentnode = thisnode;
foreach (string subPath in path.Split(cachedpathseparator))
{
if (null == currentnode.Nodes[subPath])
currentnode = currentnode.Nodes.Add(subPath, subPath);
else
currentnode = currentnode.Nodes[subPath];
}
}
return thisnode;
}
then you can use:
string[] paths = {
#"C:\WINDOWS\AppPatch\MUI\040C",
#"D:\WINDOWS\Microsoft.NET\Framework\v2.0.50727",
#"E:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI",
#"C:\WINDOWS\addins",
#"C:\WINDOWS\AppPatch",
#"C:\WINDOWS\AppPatch\MUI",
#"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI\0409"
};
TreeView treeview = new TreeView();
treeview.Nodes.Add(PopulateTreeNode2(paths, "\\"));
NOTE: maybe some string sensitivity check will be needed in both solutions,
in order to prevent some folders re creations.
because some url could be pointing to the same folder on the disk
but spelled different such as:
Windows ; WinDOWs , WINDOWS
Here's some very old code I once used to create an ASP.NET treeview from code (assuming TreeView has an ID of TreeViewFolders):
protected void Page_Load(object sender, EventArgs e)
{
GenerateTreeView(#"C:\WINDOWS\");
}
private void GenerateTreeView(string rootPath)
{
GetFolders(System.IO.Path.GetFullPath(rootPath), TreeViewFolders.Nodes);
TreeViewFolders.ExpandDepth = 1;
}
// recursive method to load all folders and files into tree
private void GetFolders(string path, TreeNodeCollection nodes)
{
// add nodes for all directories (folders)
string[] dirs = Directory.GetDirectories(path);
foreach (string p in dirs)
{
string dp = p.Substring(path.Length);
nodes.Add(Node("", p.Substring(path.Length), "folder"));
}
// add nodes for all files in this directory (folder)
string[] files = Directory.GetFiles(path, "*.*");
foreach (string p in files)
{
nodes.Add(Node(p, p.Substring(path.Length), "file"));
}
// add all subdirectories for each directory (recursive)
for (int i = 0; i < nodes.Count; i++)
{
if (nodes[i].Value == "folder")
GetFolders(dirs[i] + "\\", nodes[i].ChildNodes);
}
}
// create a TreeNode from the specified path, text and type
private TreeNode Node(string path, string text, string type)
{
TreeNode n = new TreeNode();
n.Value = type;
n.Text = text;
return n;
}
private void Form2_Load(object sender, EventArgs e)
{
treeView1.CheckBoxes = true;
foreach (TreeNode node in treeView1.Nodes)
{
node.Checked = true;
}
string[] drives = Environment.GetLogicalDrives();
foreach (string drive in drives)
{
// treeView1.Nodes[0].Nodes[1].Checked = true;
DriveInfo di = new DriveInfo(drive);
int driveImage;
switch (di.DriveType)
{
case DriveType.CDRom:
driveImage = 3;
break;
case DriveType.Network:
driveImage = 6;
break;
case DriveType.NoRootDirectory:
driveImage = 8;
break;
case DriveType.Unknown:
driveImage = 8;
break;
default:
driveImage = 2;
break;
}
TreeNode node = new TreeNode(drive.Substring(0, 1), driveImage, driveImage);
node.Tag = drive;
if (di.IsReady == true)
node.Nodes.Add("...");
treeView1.Nodes.Add(node);
}
foreach (TreeNode node in treeView1.Nodes)
{
node.Checked = true;
}
}
private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
{
if (e.Node.Nodes.Count > 0)
{
if (e.Node.Nodes[0].Text == "..." && e.Node.Nodes[0].Tag == null)
{
e.Node.Nodes.Clear();
string[] dirs = Directory.GetDirectories(e.Node.Tag.ToString());
foreach (string dir in dirs)
{
DirectoryInfo di = new DirectoryInfo(dir);
TreeNode node = new TreeNode(di.Name, 0, 1);
node.Checked = true;
try
{
node.Tag = dir;
if (di.GetDirectories().Count() > 0)
node.Nodes.Add(null, "...", 0, 0).Checked = node.Checked;
}
catch (UnauthorizedAccessException)
{
node.ImageIndex = 12;
node.SelectedImageIndex = 12;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "DirectoryLister", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
finally
{
node.Checked = e.Node.Checked;
e.Node.Nodes.Add(node);
}
}
}
}
}
}
private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
{
button1.Enabled = false;
TreeNode node = e.Node;
bool is_checked = node.Checked;
foreach (TreeNode childNode in e.Node.Nodes)
{
childNode.Checked = e.Node.Checked;
}
treeView1.SelectedNode = node;
}
I've managed to create a tree from path list using only for cycles. And it looks like it is the simpliest answer of this question at this moment.
Use this block of code to create a tree. list is the list of your files or folders, treeView1 is your TreeView.
//Creates a tree from given path list
foreach (string path in list)
{
TreeNodeCollection nodes = treeView1.Nodes;
foreach (string path_part in path.Split('\\'))
{
//Here it adds a new node (file or folder)
if (!nodes.ContainsKey(path_part))
nodes.Add(path_part, path_part);
//Go one node deeper
nodes = nodes[path_part].Nodes;
}
}
Note - this may break if you use it with paths that start with the path separator (e.g. /home/user)
And if you want to remove common parts of your paths (or remove single parent nodes), use this block of code right after the previous one:
//This removes "single" TreeNodes (common paths)
while (treeView1.Nodes.Count == 1)
{
//This "unpacks" child TreeNodes from the only parent TreeNode
for (int i = 0; i < treeView1.Nodes[0].Nodes.Count; i++)
treeView1.Nodes.Add(treeView1.Nodes[0].Nodes[i]);
//This removes parent TreeNode
treeView1.Nodes.RemoveAt(0);
}
This will generate an empty tree if all of your paths are the same.