Michael Kelley
Michael Kelley

Reputation: 3689

Windows Forms TreeView always selects a node on focus

The TreeView in Windows Forms always seems to want a node selected when it regains focus. If I have no nodes selected, and that treeview gains focus, I'll get an AfterSelect event with the first node selected, even though I didn't select it using the keyboard, mouse, or programmatically. The only workaround I can find is to check if the TreeViewCancelEventArgs.Action equals TreeViewAction.Unknown and then canceling the selection. This seems really hacky, so I'm wondering if there's another way to fix this.

Upvotes: 5

Views: 10289

Answers (5)

kylomas
kylomas

Reputation: 26

Solved the problem by sending TVM_SELECTITEM with lparam of 0.

Upvotes: 0

Ravi Patel
Ravi Patel

Reputation: 2191

Fixed my version of the same problem with following code.

private TreeNode _selectedNode;

public FormMain()
{
    InitializeComponent();
    myTreeView.LostFocus += (sender, args) => _selectedNode = myTreeView.SelectedNode;
    myTreeView.GotFocus += (sender, args) => myTreeView.SelectedNode = _selectedNode;
}

Upvotes: 0

Andrew
Andrew

Reputation: 144

I solved my version of this problem by turning TabStop off for the treeview.

Upvotes: 6

Willie
Willie

Reputation:

I had to over come this same exact problem (but on the compact framework) where the BeforeSelect event isn't exposed ( I was bummed).

But think got a fairly elegent solution and hope might help others!!

I made a derived TreeView control (so could select multiple items at once), but will also corrects the "auto" selection of the first node on getting FOCUS.

  • public class TreeView_MultSel : System.Windows.Forms.TreeView

I then overrode the event handlers as such:

/// <summary>
/// //This actually occurs AFTER actual Treeview control:
///   -  Got Focus in reality
///   -  Executed the "innate" behaviour (like a button showing "depressed")
///   -  The "innate and UNWANTED behaviour of the Treeview is to selected the first Node 
///          when gets the focus.
///The key here is the Treeview executes in this order (when Tree Selected and didn't have focus):
///   -  First the Node is selected (before OnGotFocus is executed)
///         Since when LostFocus "treeHasFocus" = false the OnAfterSelect handler isn't called!!
///
///   -  Then the OnGotFocus is called:
///         This will set treeHasFocus to True and will not react to selections
/// </summary>
/// <param name="e"></param>
protected override void OnGotFocus(EventArgs e)
{
    treeHasFocus = true;
    //base.OnGotFocus(e);
}

/// <summary>
/// Alot easier to handle here (in Derived TreeView control then using all kinds of 
///     -= events to try to prevent.
/// 
/// This was the cleanest way I could find (prevent firing of AfterSelect)
/// </summary>
/// <param name="e"></param>
protected override void OnLostFocus(EventArgs e)                
{                                                               
    treeHasFocus = false;                                       
    //base.OnLostFocus(e);
}

/// <summary>
/// -  Treeview Control defaults to selecting the first node (when gets focus)
/// -  We do NOT want this - since would automatically Highlight the first node (select)
/// -  treeHasFocus is NOT true for the first unwanted "automatic" selection of the first item
/// -  Upon loosing Focus, the AfterSelect handler is never called.
/// </summary>
/// <param name="e"></param>
protected override void OnAfterSelect(TreeViewEventArgs e)      
{                                                               
    if (treeHasFocus)                                           
        base.OnAfterSelect(e);                                   
    this.SelectedNode = null;                                   
}

Upvotes: 3

Jeff Mattfield
Jeff Mattfield

Reputation:

I agree that using TreeViewAction.Unknown in this case is less than desirable. Consider using the BeforeSelect event, which provides an opportunity to prevent the AfterSelect event.

Create a GotFocus event handler that sets a flag. Then, create a BeforeSelect event handler that, if the flag is set, cancels the event and clears the flag. For example:

private bool treeViewWasNewlyFocused = false;

private void TreeView1_BeforeSelect(object sender, TreeViewCancelEventArgs e)
{
    if(treeViewWasNewlyFocused)
    {
        e.Cancel = true;
        treeViewWasNewlyFocused = false;
    }
}

private void TreeView1_GotFocus(object sender, EventArgs e)
{
    treeViewWasNewlyFocused = true;
}

Upvotes: 6

Related Questions