WinForms TreeView - how to manually "highlight" node (like it was clicked) - c#

I would need to know how to let the programatically selected node make graphically in the state "selected" like the user clicked on it. SelectedNode only makes this one internally selected. Thank you very much!

The reason it does not show as highlighted is due to the tree view not having focus. This is in a button click event on my test form:
TreeView1.SelectedNode = TreeView1.Nodes(2);
TreeView1.Focus();
Which highlights the node properly. if you remove the Focus(); call it doesn't highlight until you click into the tree view (anywhere in the tree view, not necessarily on to the node that you want to be selected).

TreeView1.SelectedNode.BackColor = SystemColors.HighlightText; // This will work
Above solutions will only set the focus on it but will not change the highlight view of it.

This works for me for .net 3.5:
Set the treeview component's DrawMode property to: OwnerDrawAll
Then in the DrawNode event write the following:
if (((e.State & TreeNodeStates.Selected) != 0) && (!MyTreeView.Focused))
e.Node.ForeColor = Color.Blue;
else
e.DrawDefault = true;
And in the BeforeSelect event have:
if (MyTreeView.SelectedNode != null)
MyTreeView.SelectedNode.ForeColor = Color.Black;
e.Node.ForeColor = Color.Blue;

I don't know if it helps you or not but check the taborder of the the page and make sure that the tree view control has tab order of 0

Here is what I got to work:
void myProcedure()
{
// Hookup a DrawMode Event Handler
this.myTV.DrawNode += myTV_DrawNode;
// Set DrawMode and HideSelection
this.myTV.DrawMode = TreeViewDrawMode.OwnerDrawText;
this.myTV.HideSelection = false;
// Make sure the TreeView has Focus
this.myTV.Focus();
// Make sure the TreeView is Selected
this.myTV.Select();
// If the TreeView has a Node, I want to select the first Node to demonstrate.
if (this.myTV.Nodes.Count > 0)
{
// Make sure the node is visible
this.myTV.Nodes[0].EnsureVisible();
// Make sure the Node is Selected
this.myTV.SelectedNode = myTV.Nodes[0];
}
// Make sure the SelectedNode IS the Node that we programmatically want to select.
textBox1.Text = this.myTV.SelectedNode.Text;
// if we display sanityCheck1 string, it actually is the correct node.text
// Make sure .NET runtime knows the Node is selected
textBox1.Text += " is Selected = " + this.myTV.SelectedNode.IsSelected.ToString();
}
Following up: laalto answered the How to HighLight the TreeView.Node. The following code in the DrawNode Event Handler, from samball's answer, properly highlights the TreeView.Node based on its Selected State.
private void myTV_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
// first, let .NET draw the Node with its defaults
e.DrawDefault = true;
// Now update the highlighting or not
if (e.State == TreeNodeStates.Selected)
{
e.Node.BackColor = SystemColors.Highlight;
e.Node.ForeColor = SystemColors.HighlightText;
}
else
{
e.Node.BackColor = ((TreeView)sender).BackColor;
e.Node.ForeColor = ((TreeView)sender).ForeColor;
}
}
Platform = C# .NET 4.5 in Windows 10, Visual Studio 2015

TreeView1.SelectedNode = TreeView1.Nodes(2);
this.ActiveControl = TreeView1;
This works for me (.net 4.7)

The underlying Win32 control supports this (think it's TVIS_DROPHILITED), but I can't see the same functionality exposed through the TreeView control.
As theraneman says, you could fake it with the TreeNode.ForeColor and BackColor properties...

I had an similar issue and wanted to have a TreeView node selected (highlighted) on form load.
Maybe someone has the same problem, too.
I first tried Pondidum's solution. Without success.
But then I found the solution in another thread: Simply set the TabIndex of the TreeView to 0.
In that case you don't need to set the focus. Just choose the node that should be selected by using SelectedNode and set the TabIndex. That's it.

Not sure, but can you not change the background color of that node?

Related

Set none selected in Winforms TreeView component

Initially, I want nothing selected on my TreeView. By default, the first node is selected/focused.The code
treeView1.SelectedNode = null;
didn't work.
The tree node is not selected but has tap stop
treeView1.SelectedNode = null;
treeView1.TabStop = false;
Put your line of code
treeView1.SelectedNode = null;
in the Form.Shown event, rather than in the Form.Load event. The default selection occurs after Form.Load, so you want to clear the selection after that.
Put your line of code
TreeView.HideSelection = false;

WinrtXamlToolkit TreeView expand with single instead of double click

I am using the TreeView from the WinrtXamlToolkit. The default behavior of this control is to expand the nested items on double click of the header. The code responsible for this is here (TreeViewItem.cs line 1205).
private void OnHeaderMouseLeftButtonDown(object sender, PointerRoutedEventArgs e)
{
if (Interaction.AllowMouseLeftButtonDown(e))
{
// If the event hasn't already been handled and this item is
// focusable, then focus (and possibly expand if it was double
// clicked)
if (!e.Handled && IsEnabled)
{
if (Focus(FocusState.Programmatic))
{
e.Handled = true;
}
// Expand the item when double clicked
if (Interaction.ClickCount % 2 == 0)
{
bool opened = !IsExpanded;
UserInitiatedExpansion |= opened;
IsExpanded = opened;
e.Handled = true;
}
}
Interaction.OnMouseLeftButtonDownBase();
OnPointerPressed(e);
}
}
Is there a way to change this behavior to expand the items on single click or tap without actually copying the control and all it's related classes to my project?
It seems like an overkill to do this just to change a few lines of code.
I tried to do drag'n'drop stuff with that TreeView and was in a similar situation. My first move was to actually copy all the TreeView and its related classes and man there are a lot. There's a lot of internal stuff happening and I pretty much gave up interfering with it after a bunch of other stuff stopped working.
So my solution was to just have a specific control inside the ItemTemplate that handled dragging for me. For you this would be a Button whose Click you handle. In the eventhandler you will navigate up the visual tree to your TreeViewItem and change the IsExpanded.

C# ComboBox disable highlighting

I have custom ComboBox, where DropDownStyle = ComboBoxStyle.DropDown;.DropDown style is set because I want to set the Text property of the ComboBox to something outside the list of values. Everything works good, except that ComboBox is highlighting the text when it's left and when I click on the combobox editing is avaible. How can I cope with this?
To illustrate:
First Picture is where everything looks good, second is the highlight situation, third editing is on.
Try un-selecting the text after the DropDown closes:
void comboBox1_DropDownClosed(object sender, EventArgs e) {
this.BeginInvoke(new Action(() => { comboBox1.Select(0, 0); }));
}
If you are referring to disabling the highlighting and editing, then you might want to consider setting the DropdownStyle property to DropdownList.
yourComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
Tricky problem to solve. It seems to be from the Resize event. There are a lot of solutions that do something similar to this, but none that I've seen worked for me until I tried this. (This is a solution that does not require inheritance from ComboBox; inheriting is probably a much more straight forward solution, but requires you to always use your inherited class and never the actual ComboBox class.)
comboBox.Resize += (s, e) => {
if (!comboBox.IsHandleCreated)
return; // avoid possible exception
comboBox.BeginInvoke(new Action(() => comboBox.SelectionLength = 0));
};
Set the selection length to zero to get rid of the highlight, but when? Other examples do it in other places, but the problem seems to be specifically caused by Resize, so doing it after Resize fixes it consistently, at least for me. (Can still see it flicker when you resize the window though, but it always ends up ok.)
BeginInvoke ensures that it happens sufficiently after Resize to work, and the check for IsHandleCreated prevents it from being called before the handle is created, in which case BeginInvoke would throw an exception.
This slightly more complex version includes some checks to prevent a focused control from losing highlight, since it actually should have it. It also doesn't fire if the parent doesn't exist yet, or if the parent does not have an active control yet, both signs that things are too early.
comboBox.Resize += (s, e) => {
if (!comboBox.IsHandleCreated)
return;
comboBox.BeginInvoke(new Action(() => {
var parent = comboBox.FindForm();
if (parent == null)
return;
if (parent.ActiveControl == null)
return;
if (parent.ActiveControl == comboBox)
return;
comboBox.SelectionLength = 0;
}));
};
I tried to make a version that would 'preserve' the selection length rather than always set it to zero, but I couldn't get it to synchronize properly. Many Resize events can fire before the BeginInvoke delegates start to fire, so the preserved value will always be overwritten by the broken one. I tried saving them all in a Queue or Stack, but in both cases, I was unable to reverse the ordering (not really sure why, since that makes no sense).
To solve the same I have tried almost EVERYTHING:
setting the DropdownStyle property to DropdownList
this.BeginInvoke(new Action(() => { comboBox1.Select(0, 0); }));
combobox1.SelectionLength = 0;
changing comboBox.TabIndex
Not tried SendKeys.Send("{ESC}"); because it is not a reliable solution
Nothing helped.
The only stable and working solution was to move a focus on another Label control:
label.Focus();
You could also hide that label.
I know this post is old but recently I have the same problem with combobox.
Situation : I have an editable combobox which propose complete words when user write some letters.
But when I want to type a letter, combobox auto highlight the text and the next letter auto replace the previous.
Solution : I use a textbox to avoid any highlight like that:
<ComboBox IsTextSearchEnabled="False" IsEditable="True" x:Name="CMB_ClientName"/>
<TextBox Text="{Binding ElementName=CMB_ClientName, Path=Text}" TextChanged="ComboBoxChange" x:Name="TXT_ClientName"/>
And I generate the textbox TextChanged event :
private void ComboBoxChange(object sender, TextChangedEventArgs e)
{
//Clear ComboBox items
CMB_ClientName.Items.Clear();
//Auto Open DropDownList
CMB_ClientName.IsDropDownOpen = true;
//Get data from database (use entity framework 6.x)
dbEntity.Client.Load();
//Attribute Data to variable
var clients = dbEntity.Client.Local;
foreach (Client client in clients)
{
//If data begin with the texbox text, the data is add to the combobox items list.
if (client.Nom.ToLower().StartsWith(TXT_NomClient.Text.ToLower()))
{
CMB_ClientName.Items.Add(client.Nom);
}
}
}
I know this solution isn't realy beautifull, but it is for me the easiest solution to avoid highlight text and all the solutions in this post don't work for me.
I hope this solution will be helpfull, thanks for reading.
Math.
Ps: My apologies, my English is not very good. I hope you will understand me correctly.
Nothing worked for me ( I want the form to load with no highlighting in any combobox) until I set the combobox property TabStop to false. This meant that one of my buttons took the tab highlight which I didn't like so I set them all to false for start up and adjusted them programatically as needed.
I know this is an old thread, but my solution is similar to that of the others, but relies on the Form.ResizeEnd event. In its event handler, I iterate through the ComboBoxes and set ComboBox.SelectionLength to 0.
private void Form_ResizeEnd(object sender, EventArgs e)
{
foreach(ComboBox comboBox in parentControl.Controls.OfType<ComboBox>
{
comboBox.SelectionLength = 0;
}
}
This is what worked for me:
Set DrawMode to OwnerDrawFixed
Set cbxSubsystems.DrawItem event to the function below
private void cbxSubsystems_DrawItem(object sender, DrawItemEventArgs e)
{
Color BgClr;
Color TxClr;
if( (e.State & DrawItemState.ComboBoxEdit) == DrawItemState.ComboBoxEdit )
{
// Do not highlight main display
BgClr = cbxSubsystems.BackColor;
TxClr = cbxSubsystems.ForeColor;
}
else
{
BgClr = e.BackColor;
TxClr = e.ForeColor;
}
e.Graphics.FillRectangle(new SolidBrush(BgClr), e.Bounds);
TextRenderer.DrawText(e.Graphics, cbxSubsystems.Items[e.Index].ToString(), e.Font, e.Bounds,
TxClr, BgClr, TextFormatFlags.Left | TextFormatFlags.VerticalCenter );
}

How do I keep the KMLTreeView item 'selected' when the TreeView loses focus?

In Google Earth the background color of a selected item in the KMLTreeView dims when clicking on the Globe. In my C# based application the TreeView Node loses all color so I do not know which item is selected.
Similarly, I would like to have the treeview node highlight when I click on its associated placemark as also happens in GE.
I assume this is the default behavior so I must not be associating the placemarks with the kmltreeview properly. Below is the code I use for creating and adding the node to the globe as well as the kmltreeview control. Is there something I'm doing wrong or not doing to be able to use the default behavior?
Thanks!
dynamic placemark = KmlHelpers.CreatePlacemark(ge1,
Coord,
d.sSerialNumber,
d.sNickname,
"Device Type: " + d.sName + "<p>" +
"IP Address: " + d.sIPAddress + "<p>" +
"ESN: " + d.sSerialNumber + "<p>" +
"<a href=\"http://localhost/index.html#"
+ d.sSerialNumber + "\">Details</a>");
var styleMap = ge1.createStyleMap("");
// Create normal style for style map.
var normalStyle = ge1.createStyle("");
var normalIcon = ge1.createIcon("");
normalIcon.setHref("http://maps.google.com/mapfiles/kml/shapes/truck.png");
normalStyle.getIconStyle().setIcon(normalIcon);
// Create highlight style for style map.
var highlightStyle = ge1.createStyle("");
var highlightIcon = ge1.createIcon("");
highlightIcon.setHref("http://maps.google.com/mapfiles/kml/shapes/truck.png");
highlightStyle.getIconStyle().setIcon(highlightIcon);
highlightStyle.getIconStyle().setScale(2.0);
styleMap.setNormalStyle(normalStyle);
styleMap.setHighlightStyle(highlightStyle);
// Apply stylemap to a placemark.
placemark.setStyleSelector(styleMap);
kmlTreeView.ParseKmlObject(placemark);
The KmlTreeView inherits from the standard TreeView control, as such you can use the HideSelection property. By default this is set to True, however...
When this property is set to false, selected nodes in the TreeView
control remain highlighted in a different color than the current
selection color when the TreeView control loses focus. You can use
this property to keep items that are selected by the user visible when
the user clicks a different control on the form or moves to a
different window.
To do this in code, for example:
kmlTreeView.HideSelection = False;
Also, the property can be set in the visual designer for the control, simply select the KmlTreeView, then view the properties. Finally, double click on HideSelection to set it to False
UPDATE:
For the second part of the question, highlighting a node when the coorisponding feature is clicked, you would need to write a custom event handler and then use the KmlTreeView's GetNodeById method. Some thing like the following should work.
private void GEWebBrowser1OnPluginReady(object sender, GEEventArgs geEventArgs)
{
this.geWebBrowser1.AddEventListener(geEventArgs.ApiObject.getGlobe(), EventId.MouseDown);
this.geWebBrowser1.KmlEvent += geWebBrowser1_KmlEvent;
}
void geWebBrowser1_KmlEvent(object sender, GEEventArgs e)
{
// the feature that the mousedown event fired on
dynamic feature = e.ApiObject.getTarget();
// If you have other events added you will need some conditional logic here
// to sort out which event has fired. e.g.
// if(e.EventId == EventId.MouseDown)
// if(GEHelpers.IsApiType(feature, ApiType.KmlPlacemark);
// etc..
string id = feature.getId(); // the features id
KmlTreeViewNode node = myKmlTreeView.GetNodeById(id); // find the corresponding node...
if(node == null) { return; } // no corresponding node...
// set the selected node to the feature node.
myKmlTreeView.SelectedNode = node;
// make sure the node is visible in the treeview
if (!node.IsVisible)
{
node.EnsureVisible();
}
}

Setting ToolStripMenuItem.Visible to true doesn't work

I have a TreeView control for which each node in it I want to share a ContextMenuStrip which has two ToolStripMenuItems ie:
this.BuildTree = new MyApp.MainForm.TreeView();
this.ItemMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.DeleteMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ShowLogMenuItem = new System.Windows.Forms.ToolStripMenuItem();
...
this.ItemMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.DeleteMenuItem,
this.ShowLogMenuItem});
So I show and hide these to items according to certain criteria on a right click in a MouseUp event. When both are hidden I hide the ContextMenuStrip itself. Problem is when I hide the ContextMenuStrip it seems the next time I want to show one of the menu items I have to click twice on the node. The strange thing is on the first click to reshow one or both of the the items I have the following code:
ItemMenuStrip.Visible = true;
ShowLogMenuItem.Visible = true;
The two lines above don't seem to do anything ie both remain false in the debugger view after stepping over each line.
I don't think I've got any events on these values being set at least I don't have any events attached.
What am I doing wrong?
I suggest you to set:
this.BuildTree.ContextMenuStrip = this.ItemMenuStrip;
to make the menu automatically open on tree right-click.
Then subscribe ItemMenuStrip.Opening event to change the visibility of items and the contextmenu itself:
void ItemMenuStrip_Opening(object sender, CancelEventArgs e)
{
if (something)
{
e.Cancel = true; // don't show the menu
}
else
{
// show/hide the items...
}
}
If you need to know the current position of the clicked point (e.g. to check if a tree node is clicked), you can use Control.MousePosition property. Note that MousePosition is a point in screen coordinates, so you need to call treeView1.PointToClient(position) to get the tree coordinates e.g. :
private void ItemMenuStrip_Opening(object sender, CancelEventArgs e)
{
var pointClicked = this.BuildTree.PointToClient(Control.MousePosition);
var nodeClicked = this.BuildTree.GetNodeAt(pointClicked);
if (nodeClicked == null)
{
// no tree-node is clicked --> don't show the context menu
e.Cancel = true;
}
else
{
// nodeClicked variable is the clicked node;
// show/hide the context menu items accordingly
}
}
So figured out what was going wrong I was setting Visible on this.ItemMenuStrip rather than the this.BuildTree.ContextMenuStrip.
This seems rather strange to me as I would have thought BuildTree.ContextMenuStrip was just a direct reference to the ItemMenuStrip but apparently not.

Categories

Resources