Actually deselect all nodes in TreeView (.NET) - c#

I'm trying to actually deselect all nodes in my TreeView. By "actually", I mean that TreeView1.SelectedNode = null; will actually deselect the node in the tree.
Right now, visually speaking, the node is deselected. However, when I try to add a new node, the treeview will automatically select the first node in the tree (at the top) and create a subnode when ideally I want to create a parent node. I can't just deselect the selected node before adding either, because the user might want to add a child node. The behaviour I'd like is for the parent/child node adding to be based on what is selected in the treeview. If nothing is selected, add a parent, if something is selected, add a child in that selected node.
I construct a TreeNode object called node in a function with images and text and all that then I have the following:
if (tvContent.SelectedNode == null)
tvContent.Nodes.Add(node);
else
{
tvContent.SelectedNode.Nodes.Add(node);
tvContent.SelectedNode.Expand();
}
I have a "Deselect All" button that is supposed to make the above code work. The code for that button is simply:
tvContent.SelectedNode = null;
Pardon my tagging both C# and VB.NET. I'm good with both so if someone can help me out in either language that'd be terrific!
Thanks
EDIT:
Interesting. It seems that while testing if the selected node is null, .NET will automatically set the selected node to the first node in the tree. The following code shows the "trigger" message box, but immediately selects the first node in the tree after the if statement is complete.
private void btnDeselectAll_Click(object sender, EventArgs e)
{
tvContent.SelectedNode = null;
if (tvContent.SelectedNode == null) MessageBox.Show("trigger");
}
EDIT2: The issue lies in using an InputBox for the title input of the node. For whatever reason, that changes the selected node of the treeview. I tried this in a stock project and managed to replicate the issue. I guess there's no fixing this :S

So it turns out that getting "true" deselection isn't possible. As soon as the treeview loses focus then gains focus again (e.g. via an inputbox window popping up), the selected node will no longer be null.
My work around was to introduce a panel that becomes visible with some input options so that node title input is done on the main form instead of on another form. I don't like this fix but it's all that can be done.

This worked for me
Private LastSelectetNode As TreeNode
Protected Overrides Sub OnBeforeSelect(e As TreeViewCancelEventArgs)
e.Cancel = LastSelectetNode Is Nothing
MyBase.OnBeforeSelect(e)
End Sub
Protected Overrides Sub OnMouseUp(e As MouseEventArgs)
Dim nd = MyBase.HitTest(e.Location).Node
If LastSelectetNode Is nd Then
SelectedNode = Nothing
LastSelectetNode = Nothing
Else
LastSelectetNode = nd
End If
MyBase.OnMouseUp(e)
End Sub

I tried to reproduce your scenario but failed. After setting SelectedNode to null, it remained null for me when trying to read it back. A few things I want to check on:
Are you sure you're actually deselecting the node? If you have the "HideSelection" property of the TreeView set to True (default), the selection disappears anytime the TreeView loses focus (like when you click your deselect all button - making it look like it's working). Make sure this isn't the case by setting HideSelection to False.
Are you sure you're not triggering an event handler (like SelectedNodeChanged) when you set the SelectedNode to null?

Related

Treeview re-select node by code after use

When selecting a treenode in my WinForm treeview, it gets highlighted with the blue background to indicate it is selected.
Once the user hits a button, the selected node gets used in some code. In this example, when the button is pushed, the node moves up an instance.
But once the code has executed, the selection is lost. Now the user have to re-select the node by hand and hit the button again to move it up again.
So what i would want, is that the node gets re-selected after the code has executed.
i tried doing that with this code, but that does not seem to have any effect on the selection:
TreeNode t = treeView1.SelectedNode;
//do something
Extensions.MoveUp(treeView1.SelectedNode);
//re-select ?
treeView1.SelectedNode = t;
Is there some other way to set the selection again by code after executing my method ?
EDIT (SOLVED - Not deleting post in case sombody in the future is looking for the same thing):
All i had to do was cast the focus as the final step:
treeView1.Focus(); did the trick

C# replace one TreeView with another

I am building a searchable TreeView (treeView1), which will remove any TreeNode that do not contain the search keyword. However, I would like to reset the tree back to its original structure on the click of a button. I am storing the original treeview in a variable before the search is performed.
TreeView originalTreeView = new TreeView();
originalTreeView = treeView1;
I then perform the search, which is likely to remove some TreeNodes.
treeView1.searchTree(keyword);
Then, when I click the Reset button, I would like treeView1 to once again show the full originalTreeView, which is what I cannot figure out how to do.
private void resetBtn_Click(object sender, EventArgs e) {
treeView1 = originalTreeView;
}
This code does nothing (the listener is OK). Is it possible to do something like this, or do I have to populate the tree all over again every time?
Your code are assign the reference to originalTreeView only, but not copy/clone as a new object (backup).
Please try this Copy all treeView parent and children to another treeView c# WinForms

Telerik TreeView | NodeExpand event is providing the wrong node value when using NodeTemplate

I am using Telerik version: 2009.3.1208.0
My task is to add an arrow to the node (on the right side of the node) so people can left-click on it and access context menu.
I was able to to do that through creating a nodetemplate (subscribing to an interface) and then assigning my class to NodeTemplate property (on Page Init)
Here is the code:
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports Telerik.Web.UI
Public Class MyNodeTemplate
Implements ITemplate
Public Sub InstantiateIn(ByVal container As Control) Implements ITemplate.InstantiateIn
Dim newLabel As New Label()
newLabel.CssClass = "nodeLabel"
newLabel.Text = DirectCast(container, RadTreeNode).Text
Dim arrowDiv As New System.Web.UI.HtmlControls.HtmlGenericControl("DIV")
arrowDiv.Attributes.Add("class", "nodeRightClickArrow")
arrowDiv.Attributes.Add("onclick", "LeftClickContextMenuClick(event, this);")
container.Controls.Add(newLabel)
container.Controls.Add(arrowDiv)
End Sub
End Class
Everything seems fine EXCEPT:
When expanding one of the nodes, the NodeExpand Event sends the wrong value for the node that is being expanded. For example, if I expand Node 3, it gives me value (e.Node.Value) for Node 1. See picture below for more explanation. As a result wrong child nodes are loaded.
Questions:
1) Why NodeExpand is broken when NodeTemplate is being added ?
2) Any way to achieve adding an arrow to the node so people can left-click on it without overwriting NodeTemplate?
I think you need to use the Node Click method, in node click your code
protected void treeView_NodeClick(object sender, RadTreeNodeEventArgs e)
{
int id;
int.TryParse(e.Node.Value, out id);
e.Node.Expanded = true // Expand the node manually, or IsExpanded, not remember
}
need to work. Aditionaly, you cold expand the node manually using. The Telerik Documentation says that this event occurs when the node expands, so it means what happens when the node expands and i think you need you expand the node.

Treeview AfterLabelEdit Keeps Firing?

I have a tree view and it's populated with tow parent nodes, and sub nodes for each parent node. I have added like a template node "Add New" in order to do database insertion, so i add the "OnNodeMouseDoubleClick" event to begin node edit, afer that i call the "AfterlabelEdit" event and do the insertion which is successfull with no problems, but the thing is that it this event keeps firing for the numbers of the sub nodes included on the parent. Is there anything wrong or that how it does work and if so is there any solution ?
if(e.Node.IsEditing == true)
{
//your code here
e.CancelEdit = true;
}

Can I insert nodes into a TreeView during AfterLabelEdit without beginning to edit them?

I have a subclass of System.Windows.Forms.TreeView that's manually "bound" to a set of hierarchical data. I want the user to be able to edit the labels of the tree, and have the changes reflected back to the data. So I set LabelEdit to true and overrode OnAfterLabelEdit to the tune of:
protected override void OnAfterLabelEdit(NodeLabelEditEventArgs e)
{
base.OnAfterLabelEdit(e);
TreeNode node = e.Node;
if (PassesSomeValidation(e.Label))
{
MyDataNode dataNode = node.Tag as MyDataNode;
dataNode.SomeBoundValue = e.Label;
int oldIndex = node.Index;
int newIndex = RepositionChangedDataNode(dataNode);
TreeNode parent = node.Parent;
parent.Nodes.RemoveAt(oldIndex);
parent.Nodes.Insert(newIndex, node);
}
else
{
e.CancelEdit = true;
}
}
RepositionChangedDataNode() re-sorts the data and returns the index into which the change node moved after sorting. I was hoping I could simply move the edited node to reflect this move.
The problem is that this causes the node to stay in edit mode! I've tried calling EndEdit(), cloning the node before inserting it, setting LabelEdit to false and back to true, wrapping the change in BeginUpdate()/EndUpdate(), and various combinations of these ideas, but none of them have any effect.
The culprit seems to be the insertion. Even if I attempt to insert a totally new node, it will go into edit mode immediately.
So, is there any way to make TreeView not behave this way? And if not, is there a good workaround?
Some ideas I've considered:
Set a custom TreeViewNodeSorter. Would prefer not to have to sort my data twice, though.
Set a flag and delay the remove-insert step until some point after AfterLabelEdit. It works to do it during WndProc, but this feels like a big kludge that is likely to fail somehow.
Use BeginInvoke() to push the remove-insert step back onto the message queue like so:
BeginInvoke(new MethodInvoker(delegate(
{
parent.Nodes.RemoveAt(oldIndex);
parent.Nodes.Insert(newIndex, node);
}));
This works and seems cleaner to me than #2, but I know this is probably not how BeginInvoke() was intended to be used, and that it may have repercussions that my very limited knowledge of the message pump cannot predict.
If you set LabelEdit for the TreeView to false, newly added nodes will not be in edit mode.
You just have to handle the case where the user wants to edit a label: Create a handler for the MouseClick event of the TreeView, where you get the clicked node by location. Set LabelEdit to true and call BeginEdit(). At the end of your handler for the AfterLabelEdit event (and after calling EndEdit(...) at an appropriate point), set LabelEdit to false again.
This works for me, whereas the solution with BeginInvoke only changed which node was in edit mode at the end.
try create a global variable, let's say:
private bool _allowEdit;
initialize it to true,
in your OnAfterLabelEdit method set it to false after your changes:
... int oldIndex = node.Index;
int newIndex = RepositionChangedDataNode(dataNode);
TreeNode parent = node.Parent;
parent.Nodes.RemoveAt(oldIndex);
parent.Nodes.Insert(newIndex, node);
**_allowEdit = false;**
}
else ...
then capture the OnBeforeLabelEdit event like this:
protected override void OnBeforeLabelEdit(NodeLabelEditEventArgs e)
{
base.OnBeforeLabelEdit(e);
e.CancelEdit = !_allowEdit;
_allowEdit = true;
}
I noticed that just after 'AfterLabelEdit' is fired, 'BeforeLabelEdit' is refired. That's why you have to stop it right there.
If you're using databinding, shouldn't the update to the data source (SomeBoundValue) trigger a refresh of the nodes? Maybe you can force the currency manager to repopulate the tree view.... If you're worried about performance you could use one of the sorting algorithms that works well with data that's almost already sorted (e.g., NOT quicksort - merge or heapsort come to mind)
Or you could dispense with data binding entirely and manually handle the repositioning since you're already half way there with RepositionChangedDataNode()....
You could try to unhook your OnEdit handler before adding the new node and re-hooking it after. I've seen that behavior before and that's how I handled it.

Categories

Resources