Windows窗体TreeView始终选择焦点上的节点

时间:2009-04-28 23:13:31

标签: c# winforms treeview

Windows窗体中的TreeView似乎总是希望在重新获得焦点时选择一个节点。如果我没有选择节点,并且树视图获得焦点,我将选择第一个节点的AfterSelect事件,即使我没有使用键盘,鼠标或编程方式选择它。我能找到的唯一解决方法是检查TreeViewCancelEventArgs.Action是否等于TreeViewAction.Unknown,然后取消选择。这看起来真的太乱了,所以我想知道是否还有另一种解决方法。

5 个答案:

答案 0 :(得分:6)

我同意在这种情况下使用TreeViewAction.Unknown不太理想。请考虑使用BeforeSelect事件,该事件提供了阻止AfterSelect事件的机会。

创建一个设置标志的GotFocus事件处理程序。然后,创建一个BeforeSelect事件处理程序,如果设置了该标志,则取消该事件并清除该标志。例如:

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;
}

答案 1 :(得分:6)

我通过关闭TabStop for treeview解决了我的问题。

答案 2 :(得分:2)

我不得不解决同样的问题(但在紧凑的框架上),其中没有暴露BeforeSelect事件(我很沮丧)。

但是思考得到了一个相当优雅的解决方案,希望可能会帮助别人!!

我创建了一个派生的TreeView控件(因此可以一次选择多个项目),但也会在获取FOCUS时更正第一个节点的“自动”选择。

  • 公共类TreeView_MultSel:System.Windows.Forms.TreeView

然后我重写事件处理程序:

/// <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;                                   
}

答案 3 :(得分:0)

使用以下代码修复了我的相同问题的版本。

private TreeNode _selectedNode;

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

答案 4 :(得分:0)

使用lparam为0发送TVM_SELECTITEM来解决问题。