C# access to TreeNode parameter - c#

Here is code:
private static TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
var directoryNode = new TreeNode(directoryInfo.Name + " (" + DirSize(new DirectoryInfo(directoryInfo.FullName)) + " bytes)" + " (" + directoryInfo.GetFileSystemInfos().Length + " files)"+ directoryInfo.CreationTime);
foreach (var directory in directoryInfo.GetDirectories())
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
foreach (var file in directoryInfo.GetFiles())
directoryNode.Nodes.Add(new TreeNode(file.Name + " (" + file.Length + " bytes)"));
return directoryNode;
}
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
string selectedNodeText = "a";
textBox1.Text = selectedNodeText;
}
I need to access directoryInfo.CreationTime from TreeNode and display it in treeView1_AfterSelect text.Box1 but I can't find right way.

You can use the Tag property of TreeNode to put the value there and then access it in the event :
directoryNode.Tag = directoryInfo;
and then in event you can access it :
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
var directoryInfo = e.Node.Tag as DirectoryInfo;
var time = directoryinfo.CreationTime;
}
or:
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
var directoryInfo = treeView1.SelectedNode.Tag as DirectoryInfo;
var creationTime = drInfo.CreationTime;
}
Hope it helps!

Tree nodes expose the Tag property that is used to store and retrieve a custom information under nodes. It can even hold a reference to a complex structure.
https://msdn.microsoft.com/en-us/library/system.windows.forms.treenode.tag(v=vs.110).aspx

Related

Thread safety / Invoke method causes StackOverflowException

This is an app that uses WMI to fetch Local Administrator group members on a remote computer. In an attempt to make threadsafe calls to update my main UI from within Background Worker I am getting a StackOverflowException. I have copied the example from another thread on Stack. Could someone help me to identify the cause?
private void getLocalAdministrators(string serverName)
{
try
{
System.Management.ManagementScope scope = new System.Management.ManagementScope("\\\\" + serverName + "\\root\\cimv2");
scope.Connect();
StringBuilder qs = new StringBuilder();
qs.Append("SELECT PartComponent FROM Win32_GroupUser WHERE GroupComponent = \"Win32_Group.Domain='" + serverName + "',Name='" + "Administrators'\"");
System.Management.ObjectQuery query = new System.Management.ObjectQuery(qs.ToString());
System.Management.ManagementObjectSearcher searcher = new System.Management.ManagementObjectSearcher(scope, query);
foreach (System.Management.ManagementObject group in searcher.Get())
{
string groupDetails = serverName + tab + group["PartComponent"].ToString() + tab;
string domainPart = groupDetails.Split('=')[1];
domainPart = domainPart.Replace("\"","").Replace(",Name","");
string accountPart = groupDetails.Split('=')[2];
accountPart = accountPart.Replace("\"", "");
if (query != null)
{
updateUISafely(serverName + tab + domainPart + tab + accountPart);
}
else
{
updateUISafely("Error with: " + serverName);
}
}
}
catch (Exception ex)
{
updateUISafely("Error with: " + serverName + ". " + ex.Message);
}
}
public delegate void ProcessResultDelegate(string result);
void updateUISafely(string result)
{
if (textBox2.InvokeRequired)
{
var d = new ProcessResultDelegate(updateUISafely);
d.Invoke(result);
}
else
{
textBox2.AppendText(result + nl);
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string[] strArray;
strArray = textBox1.Text.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
int objectCount = strArray.Count();
int count = 0;
foreach (string str in strArray)
{
getLocalAdministrators(str);
count++;
backgroundWorker1.ReportProgress((100 * count) / objectCount);
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
foreach (string item in resultsList)
{
textBox2.AppendText(item + Environment.NewLine);
}
btnGet.Enabled = true;
}
You are invoking (aka calling) the delegate, causing it to repeatedly call updateUISafely without ever invoking on the UI thread.
You should call Invoke on the form/control instead providing the delegate as parameter.
Use:
this.Invoke(d);

How to use validation in DataGridView

In my program, when I click a particular row in DataGridView, if that row contains "\" it should pop up an error message that "\ is not allowed in name or in path". I don't know how to do that.
Here is the code:
namespace OVF_ImportExport
{
public partial class Form1 : Form
{
string sName = "";
string sPath = "";
public Form1()
{
InitializeComponent();
}
private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
sName = row.Cells[0].Value.ToString();
sPath = row.Cells[1].Value.ToString();
}
}
private void BtnCreate_Click(object sender, EventArgs e)
{
richTextBox1.Text = "";
StreamWriter file = new StreamWriter("Export.bat");
file.WriteLine("c: ");
file.WriteLine("cd \\");
file.WriteLine("cd Program Files ");
file.WriteLine("cd VMware");
file.WriteLine("cd VMware OVF Tool");
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
sName = row.Cells[0].Value.ToString();
sName = sName.Trim();
sPath = row.Cells[1].Value.ToString();
file.WriteLine("start ovftool.exe --powerOffSource vi://" + TxtUsername.Text + ":" + TxtPassword.Text + "#"
+ TxtIP.Text + sPath + " " + "\"" + TxtBrowsepath.Text + "\\" + sName + "\\" + sName + ".ovf" + "\"" + Environment.NewLine);
}
file.WriteLine("pause");
MessageBox.Show("Batch File Created","Batch File");
file.Close();
}
try using this:
// Attach DataGridView events to the corresponding event handlers.
this.dataGridView1.CellValidating += new DataGridViewCellValidatingEventHandler(dataGridView1_CellValidating);
method for above event handler:
private void dataGridView1_CellValidating(object sender,
DataGridViewCellValidatingEventArgs e)
{
// Validate the CompanyName entry by disallowing empty strings.
if (dataGridView1.Columns[e.ColumnIndex].Name == "CompanyName")
{
if (String.IsNullOrEmpty(e.FormattedValue.ToString()))
{
dataGridView1.Rows[e.RowIndex].ErrorText =
"Company Name must not be empty";
e.Cancel = true;
}
}
}

c# BackgroundWorker and Treeview in winform

Env: C#, VStudio 2013, 4.5 Framework, Winforms
Goal : Insert, inside a Treeview, the content of a folder (Sub folder + files) so that user can select those needed. Display a progressbar that show the progress of loading the files and folders in the TreeView.
What i've done so far : Everything in my goal but ...
Error: "This BackgroundWorker is currently busy and cannot run multiple tasks concurrently". I get this error sometimes when I go use other apps while my application is running.
My code :
void backgroundWorkerTreeView_DoWork(object sender, DoWorkEventArgs e)
{
var progress = (((float)(int)e.Argument / (float)totalFilesInTN) * 100);
var value = (int)Math.Round((float)progress);
backgroundWorkerTreeView.ReportProgress(value, e.Argument.ToString());
}
void backgroundWorkerTreeView_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
stStripBarMain.Value = e.ProgressPercentage;
toolStripStatusLabelPrct.Text = " Loading " + e.UserState + " of " + totalFilesInTN;
}
void backgroundWorkerTreeView_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//do the code when bgv completes its work
}
private void ListDirectory(TreeView treeView, string path)
{
try
{
treeView.Nodes.Clear();
if (path != "")
{
var rootDirectoryInfo = new DirectoryInfo(path);
treeView.Nodes.Add(CreateDirectoryNode(rootDirectoryInfo, 0));
}
}
catch (Exception e)
{
txtLog.Text = txtLog.Text + "[" + DateTime.Now + "] " + e.Message + "\r\n";
}
}
private TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo, int indice)
{
var directoryNode = new TreeNode(directoryInfo.Name);
foreach (var directory in directoryInfo.GetDirectories())
{
if ((directory.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden)
{
directoryNode.Nodes.Add(CreateDirectoryNode(directory, indice));
}
}
foreach (var file in directoryInfo.GetFiles())
{
if ((IsNullOrEmpty(ext)) ||
(Array.IndexOf(ext, Path.GetExtension(file.Name.ToLowerInvariant())) >= 0))
{
if ((GetTriggerEvent(file.FullName).Contains(txtParamEvent.Text)) || (txtParamEvent.Text == ""))
{
indice++;
backgroundWorkerTreeView.RunWorkerAsync(indice);
TreeNode newTN = new TreeNode();
newTN.Text = file.Name + #" (" + GetTriggerEvent(file.FullName) + #")";
newTN.Name = file.FullName;
directoryNode.Nodes.Add(newTN);
newTN.Tag = "msg";
}
}
Application.DoEvents();
}
return directoryNode;
}
Thanks for the help
Richard

My for statement isn't working properly

I have tried so much different iterations of the for loops and all of them dont work properly or work only halfway. So I cant figure it out.
Heres my form:
So what its supposed to do is create a folder for each node in the treeview (Named FolderTV) when I click the Create folders button.
What it currently does is only creates the New_Mod folder and the Data folder nothing else. I want it to create a folder for every node and subnode. For example it would create the New_Mod folder and then within that folder It will create the Data, Models, and Textures folder and within the Data folder it would create a Scripts folder.
Here's my code for that button:
private void button3_Click(object sender, EventArgs e)
{
for (int i = 0; i <= FoldersTV.Nodes.Count; i++)
{
FoldersTV.SelectedNode = FoldersTV.TopNode;
MessageBox.Show("Current Node: " + FoldersTV.SelectedNode.Text.ToString());
Directory.CreateDirectory(SEAppdata + "\\" + FoldersTV.SelectedNode.Text.ToString());
for (int x = 0; x <= FoldersTV.Nodes.Count; x++)
{
TreeNode nextNode = FoldersTV.SelectedNode.NextVisibleNode;
MessageBox.Show("Next Node: " + nextNode.Text.ToString());
Directory.CreateDirectory(SEAppdata + "\\" + FoldersTV.SelectedNode.Text.ToString() + "\\" + nextNode.Text.ToString());
x++;
}
i++;
}
}
Try this (untested) recursive solution and try to understand it first ;)
private void CreateDirs(string path, IEnumerable<TreeNode> nodes) {
foreach(var node in nodes) {
// string dir = path + "\\" + node.Text;
string dir = Path.Combine(path, node.Text);
Directory.CreateDirectory(dir);
CreateDirs(dir, node.Nodes);
}
}
private void button3_Click(object sender, EventArgs e) {
CreateDirs(SEAppdata, FoldersTV.Nodes);
}
EDIT: Version with few debug printouts:
// using System.Diagnostics;
private void CreateDirs(string path, IEnumerable<TreeNode> nodes) {
// iterate through each node (use the variable `node`!)
foreach(var node in nodes) {
// combine the path with node.Text
string dir = Path.Combine(path, node.Text);
// create the directory + debug printout
Debug.WriteLine("CreateDirectory({0})", dir);
Directory.CreateDirectory(dir);
// recursion (create sub-dirs for all sub-nodes)
CreateDirs(dir, node.Nodes);
}
}
See: System.Diagnostics.Debug.WriteLine

Value stored in a variable in an event handler is null later on, why?

In my code I write the value from DropDownList1.SelectedItem.Text to Label1.Text and into uploadFolder in the DropDownList1_SelectedIndexChanged method. When the ASPxUploadControl1_FileUploadComplete method is called, the value is in Label1.Text but not in uploadFolder, which is null. Why is this?
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
if (DropDownList1.SelectedItem != null)
{
Label1.Text = "You selected " + DropDownList1.SelectedItem.Text;
uploadFolder = DropDownList1.SelectedItem.Text;
}
}
protected void ASPxUploadControl1_FileUploadComplete(object sender, DevExpress.Web.ASPxUploadControl.FileUploadCompleteEventArgs e)
{
if (e.IsValid)
{
string uploadDirectory = Server.MapPath("~/files/");
//string uploadDirectory = #"\\DOCSD9F1\TECHDOCS\";
string fileName = e.UploadedFile.FileName;
string path = (uploadDirectory + uploadFolder + "/" + fileName);
//string path = Path.Combine(Path.Combine(uploadDirectory, uploadFolder), fileName);
e.UploadedFile.SaveAs(path);
e.CallbackData = fileName;
}
}
It looks like uploadFolder is a variable you've declared on your page, something like this:
public class MyPage : System.Web.UI.Page
{
string uploadFile = null;
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
// Your code here
}
protected void ASPxUploadControl1_FileUploadComplete(object sender, DevExpress.Web.ASPxUploadControl.FileUploadCompleteEventArgs e)
{
// Your code here
}
}
What's happening is that the content of uploadFile that you're setting in DropDownList1_SelectedIndexChanged isn't being preserved between post-backs, because it isn't a property of one of the controls on the page. You need to store the value somewhere that gets persisted, such as the View State or in Session State.
To do this, you should add to the DropDownList1_SelectedIndexChanged method so it reads something like:
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
if (DropDownList1.SelectedItem != null)
{
Label1.Text = "You selected " + DropDownList1.SelectedItem.Text;
Session["UploadFolder] = DropoDownList1.SelectedItem.Text;
}
}
And adjust the ASPxUploadControl1_FileUploadComplete method so it extracts `uploadFolder from the Session:
string path = (uploadDirectory + Session["UploadFolder"] + "/" + fileName);
If you want to make it look more elegant than that, consider using ViewState in this sort of way:
public string UploadFolder
{
get
{
return (string)ViewState["UploadFolder"];
}
set
{
ViewState["UploadFolder"] = value;
}
}
You can then do this:
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
if (DropDownList1.SelectedItem != null)
{
Label1.Text = "You selected " + DropDownList1.SelectedItem.Text;
UploadFolder = DropoDownList1.SelectedItem.Text;
}
}
And:
string path = (uploadDirectory + UploadFolder + "/" + fileName);
I would imagine that you are not persisting uploadFolder through page post backs. Store the value in a hidden field, e.g.:
<asp:HiddenField ID="hidden_UploadFolder" runat="server" />
And then:
hidden_UploadFolder.Value = DropDownList1.SelectedItem.Text;
You can then read it again on the next post back:
string uploadFolder = hidden_UploadFolder.Value;
Make sure you add error trapping.
It looks like you are setting the value for upload folder in one postback and using it in another. If you want to persist data between postbacks use the Session.
ex.
Session["uploadFolder"] = DropDownList1.SelectedItem.Text;
string path = (uploadDirectory + Session["uploadFolder"].ToString() + "/" + fileName);
Try
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
if (DropDownList1.SelectedItem != null)
{
Label1.Text = "You selected " + DropDownList1.SelectedItem.Text;
Session["uploadFolder"] = DropDownList1.SelectedItem.Text;
}
}
protected void ASPxUploadControl1_FileUploadComplete(object sender, DevExpress.Web.ASPxUploadControl.FileUploadCompleteEventArgs e)
{
if (e.IsValid)
{
string uploadDirectory = Server.MapPath("~/files/");
//string uploadDirectory = #"\\DOCSD9F1\TECHDOCS\";
string fileName = e.UploadedFile.FileName;
string uploadfolder = Session["uploadFolder"] as String;
string path = (uploadDirectory + uploadfolder + "/" + fileName);
//string path = Path.Combine(Path.Combine(uploadDirectory, uploadFolder), fileName);
e.UploadedFile.SaveAs(path);
e.CallbackData = fileName;
}
}

Categories