In my application I am using a tree view. When the user clicks on the [+] to expand a node, that node changes to the selected node. How can I stop this?
private void tvFileStructure_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
if (e.Node.Text != "Network")
{
int unauthorisedAccessExceptions = 0;
try
{
TreeNode newSelected = e.Node;
DirectoryInfo nodeDirInfo = (DirectoryInfo)newSelected.Tag;
TreeNode child = newSelected.FirstNode;
if (child.Level < 3)
{
while (child != null)
{
// Only try to populate if there aren't any children
if (child.FirstNode == null)
{
DirectoryInfo[] subDirs = ((DirectoryInfo)child.Tag).GetDirectories();
if (subDirs.Length != 0)
{
getDirectories(subDirs, child);
}
}
child = child.NextNode;
}
}
}
catch (UnauthorizedAccessException)
{
unauthorisedAccessExceptions++;
}
if (unauthorisedAccessExceptions > 0)
{
MessageBox.Show("There were " + unauthorisedAccessExceptions.ToString() + " folder(s) that you do not have access to.", "Warning...", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
}
As Hans mentioned this is not the default behavior of the standard WinForms TreeView. However, you can cancel the selection changing in the BeforeSelect event:
void tvFileStructure_BeforeSelect(object sender, TreeViewCancelEventArgs e)
{
if (iDontWantToSelectThis)
{
e.Cancel = true;
}
}
Related
What I'm trying to do is: I have a datagrid which is populated. The last column is a button and i have a time countdown which then presses a button and populates the datagrid. I then want to loop the datagrid and press the button programmatically (like a .PerformClick()) action.
CellContentClick
private void dgView_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (toolStrip.Text != "You are successfully logged in ...") {
Helpers.returnMessage("You are not logged in ... aborting ...");
return;
}
// once found we execute: reportBackFound() and update the database
//Helpers.returnMessage("Clicked programatically!");
var senderGrid = (DataGridView)sender;
string rowId = senderGrid.Rows[e.RowIndex].Cells[0].Value.ToString();
string rowNm = senderGrid.Rows[e.RowIndex].Cells[1].Value.ToString();
string rowUi = senderGrid.Rows[e.RowIndex].Cells[2].Value.ToString();
if (senderGrid.Columns[e.ColumnIndex] is DataGridViewButtonColumn && e.RowIndex >= 0)
{
try {
XmlDocument doc = new XmlDocument();
doc.Load("https://www.thesite.com/api.php?getApiData=1");
XmlNodeList _nodeList = doc.SelectNodes("/api/apiData");
foreach (XmlNode _node in _nodeList)
{
if (rowNm == _node["apiName"].InnerText)
{
// here we do an http webrequest to the url: _node["apiUrl"].InnerText we look for: zd_show.cgi? in the html
// if we find this it's a success.
var success = _useratorRequester.getReportsPage(_node["apiUrl"].InnerText);
if (success.Contains("zd_show.cgi?"))
{
reportBackFound(int.Parse(rowId), int.Parse(_node["apiId"].InnerText));
updateTheLog(int.Parse(rowId), _node["apiName"].InnerText, int.Parse(rowUi), "success");
} else {
// just update the reports log ...
updateTheLog(int.Parse(rowId), _node["apiName"].InnerText, int.Parse(rowUi), "in-progress");
}
if (chkBoxDebug.Checked)
{
File.AppendAllText("Debug\\userator-social.html", success, Encoding.GetEncoding("windows-1251"));
}
} else {
// there is no project in the userator system ...
}
}
} catch (Exception ex) {
Helpers.returnMessage("API TASKS:\n\n" + ex.ToString());
}
}
}
Timer
private void timerCountDown_Tick(object sender, EventArgs e)
{
counter--;
if (counter == 0)
{
timerCountDown.Stop();
btnParseTasks.PerformClick();
foreach (DataGridViewRow row in dgView.Rows) {
if (row.Cells["col4"].Value.ToString() == "Action") {
// perform click event
dgView_CellContentClick(dgView, new DataGridViewCellEventArgs(0, 0));
}
}
counter = 5;
}
lblCountDown.Text = counter.ToString() + " seconds until next check.";
}
I know I need to launch the event handler:
dgView_CellContentClick(dgView, new DataGridViewCellEventArgs(0, 0));
this line is not correct, I'm not sure what to pass in for DataGridViewCellEventArgs.
When adding files to the listView1 in this method i do have the property Items.
private void AddFiles(string strPath)
{
listView1.BeginUpdate();
listView1.Items.Clear();
iFiles = 0;
try
{
DirectoryInfo di = new DirectoryInfo(strPath + "\\");
FileInfo[] theFiles = di.GetFiles();
foreach(FileInfo theFile in theFiles)
{
iFiles++;
ListViewItem lvItem = new ListViewItem(theFile.Name);
lvItem.SubItems.Add(theFile.Length.ToString());
lvItem.SubItems.Add(theFile.LastWriteTime.ToShortDateString());
lvItem.SubItems.Add(theFile.LastWriteTime.ToShortTimeString());
listView1.Items.Add(lvItem);
}
}
catch(Exception Exc) { statusBar1.Text = Exc.ToString(); }
listView1.EndUpdate();
}
But now i want to add properties so when i'm doing mouse right click on a file it will show a contextmenu:
private void listView1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
int index = listView1.IndexFromPoint(e.Location);
if (index != ListBox.NoMatches)
{
listJobs.SelectedIndex = index;
Job job = (Job)listJobs.Items[index];
ContextMenu cm = new ContextMenu();
AddMenuItem(cm, "Run", QueueForRun, job).Enabled = !job.Pending;
AddMenuItem(cm, "Cancel run", CancelQueueForRun, job).Enabled = (job.State == JobState.Pending || job.State == JobState.Running);
AddMenuItem(cm, "Open folder", OpenFolder, job);
cm.Show(listJobs, e.Location);
}
}
}
This time i don't have IndexFromPoint and also not Items
Because IndexFromPoint() is a ListBox method, ListView has not. In ListView there is GetItemAt() method to achieve same result.
var item = listView.GetItemAt(e.Location.X, e.Location.Y);
if (item != null) {
listJobs.SelectedIndex = item.Index; // Assuming listJobs is a ListBox
}
EDIT: according to your comment if listJobs is a ListView too then it has not SelectedIndex but it has SelectedIndices, simply:
listJobs.SelectedIndices.Clear();
listJobs.SelectedIndices.Add(item.Index);
You have first to clear the list because, by default, MultiSelect is true then you may select multiple items.
I have a Treeview with checkboxes when I click the parent node checkbox that child node will also be checked
I want to get the checked child node value
In the below code I got all the checked values even parent node value
But I don't want that parent node.
protected void btnAdd_Click(object sender, EventArgs e)
{
if (TreeView1.CheckedNodes.Count > 0)
{
foreach (TreeNode node in TreeView1.CheckedNodes)
{
string checkedValue = node.Text.ToString();
activityData = new ActivityData { ActivityName = checkedValue };
listActivity.Add(activityData);
Session["listActivity"] = listActivity;
}
}
}
In the above image I don't want to get HR Activity(Parent node)
Any ideas? Thanks in advance
Use the following code. The main parent node does not have a parent.
You only need to set the session variable at the end of the foreach
Keep in mind that accesing or assigning session variables means that a deserialization/serialization of the object is happening
Also I dont know if maybe you need to clear or initialize the listActivity before the foreach. You can do this either with
listActivity = new List<ActivityData>() ;
or
listActivity.Clear();
Here is the code
protected void btnAdd_Click(object sender, EventArgs e)
{
if (TreeView1.CheckedNodes.Count > 0)
{
foreach (TreeNode node in TreeView1.CheckedNodes)
{
//The main parent node does not have a parent
if(node.Parent != null)
{
string checkedValue = node.Text.ToString();
activityData = new ActivityData { ActivityName = checkedValue };
listActivity.Add(activityData);
}
}
//stablish the session variable only when the foreach has finished
Session["listActivity"] = listActivity;
}
}
There's a property of a treeview node called Level, so you could skip nodes with a level of 0, course that will break down if you nest a level deeper.
If you know which parent node it is, then iterate through it's children and test for checked.
protected void btnAdd_Click(object sender, EventArgs e)
{
if (TreeView1.CheckedNodes.Count > 0)
{
foreach (TreeNode node in TreeView1.CheckedNodes)
{
if (node.Level > 0)
{
string checkedValue = node.Text.ToString();
activityData = new ActivityData { ActivityName = checkedValue };
listActivity.Add(activityData);
Session["listActivity"] = listActivity;
}
}
}
}
I am using Ext.net TreePanel which does not have an option to skip the root node.
Basically, I have the following code
protected void Page_Load(object sender, EventArgs e)
{
SiteMapNode siteNode = SiteMap.RootNode;
Ext.Net.TreeNode root = this.CreateNode(siteNode);
root.Draggable = false;
root.Expanded = true;
TreePanel1.Root.Add(root);
}
private Ext.Net.TreeNode CreateNode(SiteMapNode siteMapNode)
{
Ext.Net.TreeNode treeNode = new Ext.Net.TreeNode();
treeNode.NodeID = siteMapNode.Key;
treeNode.Text = siteMapNode.Title;
treeNode.Qtip = siteMapNode.Description;
SiteMapNodeCollection children = siteMapNode.ChildNodes;
if (children != null && children.Count > 0)
{
foreach (SiteMapNode mapNode in siteMapNode.ChildNodes)
{
treeNode.Nodes.Add(this.CreateNode(mapNode));
}
}
return treeNode;
}
Could you please help to skip the parent node in the above example.
Thank you and regards.
A Root Node is required, although you can set RootVisible="false" on your <ext:TreePanel /> to hide it.
Hope this helps.
I am having a treeview initially with a root node when form is loaded. I will add child node as some.txt file at the runtime by selecting an option as Addnew from contextmenu which was displayed when the user right clicks on the root node. Now what i need is if the tree has child node appended to the Root and if user tries to create a new node by clicking the option addnew from context menu i would like to display an error as only one child allowed.
My sample code to add a child node is as follows
private void AddNew_Click(object sender, EventArgs e)
{
//if (tvwACH.Nodes.Count==1)
//{
// MessageBox.Show("Only One File allowed");
//}
//else
//{
if (tvwACH.SelectedNode.Text != null)
{
string strSelectedNode = tvwACH.SelectedNode.Text.ToString();
switch (strSelectedNode)
{
case "ACH":
{
Stream myStream;
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.InitialDirectory = #"C:\";
saveFileDialog1.DefaultExt = "txt";
saveFileDialog1.Filter = "(*.txt)|*.txt";
saveFileDialog1.FilterIndex = 2;
saveFileDialog1.RestoreDirectory = true;
saveFileDialog1.ValidateNames = true;
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
FileName = saveFileDialog1.FileName;
if (FileName.Contains(" \\/:*?<>|"))
{
MessageBox.Show("File name should not contain \\/:*?<>|", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
if ((myStream = saveFileDialog1.OpenFile()) != null)
{
FileName = saveFileDialog1.FileName;
TreeNode newNode = new TreeNode(FileName);
newNode.SelectedImageIndex = 1;
tvwACH.SelectedNode.Nodes.Add(newNode);
TreeNode NodeFileHeader = newNode.Nodes.Add("FileHeader");
myStream.Close();
}
}
}
break;
}
case "FileHeader":
{
sr = new StreamReader(FileName);
strLen = sr.ReadLine();
if (strLen == null)
{
sr.Close();
Form frmFileHeader = new frmFileHeader(this);
frmFileHeader.ShowDialog(this);
}
else
{
MessageBox.Show("Only One File Header is allowed for a file", "", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
break;
}
case "BatchHeader":
{
Form frmBatch = new frmBatch(this);
frmBatch.ShowDialog();
break;
}
}
}
//}
}
No user ever likes to get slapped with a message box that tells her she did something dumb. Improve your user interface, simply disable the menu item if it shouldn't be used. Use the context menu's Opening event, like this:
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) {
addNewToolStripMenuItem.Enabled = tvwACH.Nodes.Count > 1;
}