2009-04-28 160 views
4

Windows窗體中的TreeView總是似乎希望在重新獲得焦點時選擇一個節點。如果我沒有選擇節點,並且樹視圖獲得焦點,那麼即使未使用鍵盤,鼠標或編程方式選擇它,我也會在第一個節點被選中的情況下得到一個AfterSelect事件。我能找到的唯一解決方法是檢查TreeViewCancelEventArgs.Action是否等於TreeViewAction.Unknown,然後取消選擇。這看起來很詭異,所以我想知道是否有另一種方法來解決這個問題。Windows窗體TreeView總是選擇焦點上的節點

回答

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

與此代碼會發生什麼,如果有當樹視圖得到集中選擇一個節點發送LPARAM TVM_SELECTITEM解決的問題。然後BeforeSelect不會被提出,treeViewHasNewlyFocused將保持爲真。我的猜測是,這將導致從用戶的下一個故意節點選擇被取消。 – 2009-04-29 06:44:34

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

我解決我的版本這個問題通過打開接受tab關閉爲treeview。

0

使用以下代碼修復了我的版本問題。

private TreeNode _selectedNode; 

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