C# WinForms - TreeView, Context Menu - winforms

Suppose I am using a context menu to add child nodes to a treeview control.
(1) I am right-clicking on the node
(2)context menu pop up
(3)then I click "Add" menu item
(4)a dialogBox opens up
(5) I input the name in that DialogBox and press OK
(6) A new Node is created.
How can I get the reference of the current Node when I am clicking on the context menu item?
I need this coz the parent object is stored in the Tag property of the current node.

If you handle TreeNodeMouseClick, then your TreeNodeMouseClickEventHandler will be passed a TreeNodeMouseClickEventArgs argument.
TreeNodeMouseClickEventArgs.Node will be the TreeNode reference you want. See the TreeNodeMouseClick docs for an example similar to:
void treeView1_NodeMouseClick(object sender,
TreeNodeMouseClickEventArgs e)
{
TreeNode theTreeNodeIWant = e.Node
}
If you need to, you can store a reference in a member variable so another method can access it.

You can get the mouse position from
System.Windows.Forms.Cursor.Position
Save this before showing the context menu.
Then use the method on the Treeview containing your items
GetChildAtPoint(Point)
and add a child below that.

Related

Builder C++ : TTreeView with checkbox items

I need to create a treeview with checkbox node like this image :
How to do that?
thx!
The TTreeView component does not natively support checkboxes, but the standard Windows TREEVIEW control does, via the TVS_CHECKBOXES style:
TVS_CHECKBOXES
Version 4.70. Enables check boxes for items in a tree-view control. A check box is displayed only if an image is associated with the item. When set to this style, the control effectively uses DrawFrameControl to create and set a state image list containing two images. State image 1 is the unchecked box and state image 2 is the checked box. Setting the state image to zero removes the check box altogether. For more information, see Working with state image indexes.
Version 5.80. Displays a check box even if no image is associated with the item.
Once a tree-view control is created with this style, the style cannot be removed. Instead, you must destroy the control and create a new one in its place. Destroying the tree-view control does not destroy the check box state image list. You must destroy it explicitly. Get the handle to the state image list by sending the tree-view control a TVM_GETIMAGELIST message. Then destroy the image list with ImageList_Destroy.
If you want to use this style, you must set the TVS_CHECKBOXES style with SetWindowLong after you create the treeview control, and before you populate the tree. Otherwise, the checkboxes might appear unchecked, depending on timing issues.
To apply the TVS_CHECKBOXES style to a TTreeView component, you should derive a new component and override the virtual CreateParams() method, eg:
class TMyTreeView : public TTreeView
{
protected:
virtual void __fastcall CreateParams(TCreateParams &Params);
};
void __fastcall TMyTreeView::CreateParams(TCreateParams &Params)
{
TTreeView::CreateParams(Params);
Params.Style |= TVS_CHECKBOXES;
}
To assign the checkbox states in code, you can then use the TreeView_GetItem()/TreeView_SetItem() macros to toggle a node's state image index as needed.
Alternatively, a more flexible approach is to simply assign your own TImageList to the TTreeView::StateImages property and fill it with whatever checkbox images you want, and then you can set the TTreeNode::StateIndex property as needed. To react to user input on the checkboxes, use the TTreeView::OnClick and TTreeView::OnKeyDown events to toggle the TTreeNode::StateIndex accordingly:
void __fastcall ToggleTreeNodeCheckBox(TTreeNode *Node)
{
if ((Node) && (Node->StateIndex != -1))
{
if (Node->StateIndex == MyCheckedStateImageIndex)
Node->StateIndex = MyUncheckedStateImageIndex;
else
Node->StateIndex = MyCheckedStateImageIndex;
}
}
void __fastcall TMyForm::TreeView1Click(TObject *Sender)
{
TPoint P;
::GetCursorPos(&P);
// or: P = Mouse->CursorPos;
// or: POINTS pts = MAKEPOINTS(::GetMessagePos()); P = Point(pts.x, pts.y);
P = TreeView1->ScreenToClient(P);
if (TreeView1->GetHitTestInfoAt(P.x, P.y).Contains(htOnStateIcon))
ToggleTreeNodeCheckBox(TreeView1->GetNodeAt(P.x, P.y));
}
void __fastcall TMyForm1::TreeView1KeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
{
if (Key == VK_SPACE)
ToggleTreeNodeCheckBox(TreeView1->Selected);
}

Opening tab with tree node data

Hi,
I'm new to both Prism and WPF, and I have a question regarding sharing data between views.
Application I'm working on resembles SQL Server Development Studio. Demo contains two regions. First region contains tree (like Object explorer in SQL Server DS). Tree nodes are bound to different view models. Example would be DatabaseA->Tables->dbo.TableA->Columns etc.
Second region is initially empty. When I double click on tree node I would like to open view that displays data I clicked in tree.
In detail:
1. double click on tree node
2. node data and display it in second region
3. if second region isn't empty, check if clicked node data is already displayed in one of existing tab pages
4. if not, create new tab page with clicked node data, otherwise focus existing tab page
Until now, I managed to created tree. When tree node is clicked app calls:
UriQuery uriQuery = new UriQuery {{"ID", unit.Id.ToString()}};
uriQuery.Add("TypeName", "Unit");
var uri = new Uri("DebugTreeItemView" + uriQuery, UriKind.Relative);
RegionManager.RequestNavigate("SECOND_REGION", uri);
This will open view with tab control and I can fetch uri parameters. But I'm not satisfied with this solution. I need a way to:
1. intercept this RegionManager.RequestNavigate call in order to check if tab control is alread created. Also, I need to check that clicked node data isn't already displayed in one of existing tab pages.
2. I would like to send Unit object directly to tab control view instead of sending ID and typename. What is the best way to achieve this?
Thanks.
I would have a ShellViewModel controlling my overall application. It would contain the TreeNode collection for the left side, and the OpenTabs collection for the right side. It would also contain the SelectedTabIndex for the right side, and perhaps the SelectedTreeNode for the left side if it made sense to do so.
When you want to open a new Tab, I would use the EventAggregator to publish an OpenTab event and pass it the selected TreeNode item. The ShellViewModel would subscribe to those events, and would determine if that object already existed in the OpenTabs collection. If it exists, it simply sets the SelectedTabIndex. If not, it adds the item to the OpenTabs collection before setting the SelectedTabIndex
A while back I posted something here on this sort of navigation with MVVM if you're interested

How can I remove a class from a treenode while dragging?

I have a dynamically populated Ext.tree.TreePanel. I can drag nodes from the tree and drop them in a panel but when I drag them, the nodes default iconclass also appears in the drag proxy. How do I remove that class?
I haven't tested this, but just looking through some of the source code, the dragged ghost is obtained via an TreeNode element clone, so you can't tell it explicitly not to add your class, but the first chance you get to delete the class is in the TreePanel.startdrag event:
removeClassOnStartDrag = function(tree) {
tree.dragZone.proxy.ghost.removeClass('some-class');
}
...
treepanel.on('startdrag', removeClassOnStartDrag, this);

How do I expand treeview node by clicking on section header (Silverlight)

How do I expand the node by clicking on the item text?
Purpose is to make it easier to expand or close a node, apart from depending on the Expander arrow button.
This seems to work. This toggles the item expanded/collapsed, but you could do item.IsExpanded = true; instead if you like.
TreeViewItem item = (TreeViewItem)treeView.ItemContainerGenerator.ContainerFromItem(treeView.SelectedItem);
item.IsExpanded = !item.IsExpanded;
You can fire this code in the mouse-button-up event handler of your label. If you put it in the mouse-down event handler, the tree view item won't have been selected yet.

ContextMenuStrip loses the focus from an item in the tree view if it is right clicked

I have a contextmenuStrip associated with a tree view.
Now for instance, i have four nodes in the tree structure and Node 4 is selected.
Behavior:
ContextMenuStrip - When u right click on the Node 2 , that node is selected and as soon as the context menu strip opens up, the focus goes back to Node 4.
With old component 'Context Menu' this functionality works fine i.e. Node 2 has the focus till the time context menu is open.
I would like to have Node 2 selected as long as context menu is open. And selection/focus shall go back to Node 4 when context menu is closed.
Request please advice.
Thanks and Best Regards
Sumit
Yes, the TreeView control is pretty flaky when the focus is changed while one of its events runs. Which is one reason it distinguishes the BeforeXxxx and AfterXxxx events. Unfortunately, the context menu strip is shown too soon. The solution is to display the context menu yourself by implementing the NodeMouseClick event. Like this:
private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) {
if (e.Button == MouseButtons.Right) {
treeView1.SelectedNode = e.Node;
contextMenuStrip1.Show(treeView1, e.Location);
}
}
I'll leave restoring the focus afterwards up to you. It doesn't make much sense to implement it.

Resources