2011-05-11 53 views
3

我試圖以編程方式將鍵盤焦點設置爲樹視圖項目(在某些條件下)。我已經嘗試了兩種設置焦點的方法,它們都成功獲得了TreeViewItem的焦點,但失去了鍵盤焦點。如何以編程方式將鍵盤焦點放在WPF TreeViewItem上?

樹視圖綁定到一個視圖模型:

<TreeView Name="solutionsModel" TreeViewItem.Selected="solutionsModel_Selected" 
      ItemsSource="{Binding Items, Mode=OneWay}" /> 

我試圖通過TreeViewItemSelected路由事件將焦點設置:

private void solutionsModel_Selected(object sender, RoutedEventArgs e) 
{ 
    if (solutionsModel.SelectedItem != null && solutionsModel.SelectedItem is SolutionViewModel) 
    { 
     if (e.OriginalSource != null && e.OriginalSource is TreeViewItem) 
     { 
      FocusManager.SetFocusedElement(solutionsModel, e.OriginalSource as TreeViewItem); 
     } 
    } 
} 

我試圖將焦點設置ControlTemplate

<Style d:IsControlPart="True" TargetType="{x:Type TreeViewItem}"> 
    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type TreeViewItem}"> 
       <ControlTemplate.Triggers> 
        <Trigger Property="IsSelected" Value="true"> 
         <Trigger.Setters> 
          <Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}"></Setter> 
         </Trigger.Setters> 
        </Trigger> 
        <MultiTrigger> 
         <MultiTrigger.Conditions> 
          <Condition Property="IsSelected" Value="true" /> 
          <Condition Property="IsSelectionActive" Value="false" /> 
         </MultiTrigger.Conditions> 
         <!-- 
         <MultiTrigger.Setters> 
          <Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}"></Setter> 
         </MultiTrigger.Setters> 
         --> 
        </MultiTrigger> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

這兩種方法都會獲得焦點,但會失去鍵盤焦點(​​爲false)。窗口中沒有其他元素具有我可以說的焦點或鍵盤焦點(在測試中,在另一個面板上只有一個只讀文本框可以獲得焦點)。有趣的是,我可以將鍵盤專注於(註釋掉)MultiTrigger,其中IsSelectionActive是錯誤的,但當然這會使鍵盤始終集中在TreeViewItem上。

有沒有另一種方法獲得鍵盤焦點的更好機會,以及在哪些情況下無法獲得鍵盤焦點?

回答

2

可能有更好的方法,但我找到了一種方法,通過擴展TreeViewTreeViewItem來做到這一點,有一個單獨的NeedsFocus屬性來觸發何時設置焦點。

樹視圖:

<local:ModelTreeView x:Name="solutionsModel" ItemsSource="{Binding Items, Mode=OneWay}"> 
    </local:ModelTreeView> 

更新的(部分)控制的模板:

<Style d:IsControlPart="True" TargetType="{x:Type local:ModelTreeViewItem}"> 
    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> 
    <Setter Property="NeedsFocus" Value="{Binding NeedsFocus, Mode=TwoWay}" /> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type local:ModelTreeViewItem}"> 
       <ControlTemplate.Triggers> 
        <Trigger Property="NeedsFocus" Value="true"> 
         <Trigger.Setters> 
          <Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}"></Setter> 
         </Trigger.Setters> 
        </Trigger> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

擴展類:

public class ModelTreeView : TreeView 
{ 
    protected override DependencyObject GetContainerForItemOverride() 
    { 
     return new ModelTreeViewItem(); 
    } 

    protected override bool IsItemItsOwnContainerOverride(object item) 
    { 
     return item is ModelTreeViewItem; 
    } 
} 

public class ModelTreeViewItem : TreeViewItem 
{ 
    ///-------------------------------------------------------------------------------- 
    /// <summary>This property gets or sets whether the item needs focus.</summary> 
    ///-------------------------------------------------------------------------------- 
    public static readonly DependencyProperty NeedsFocusProperty = DependencyProperty.Register("NeedsFocus", typeof(bool), typeof(ModelTreeViewItem)); 
    public bool NeedsFocus 
    { 
     get 
     { 
      return (bool)GetValue(NeedsFocusProperty); 
     } 
     set 
     { 
      SetValue(NeedsFocusProperty, value); 
     } 
    } 

    protected override DependencyObject GetContainerForItemOverride() 
    { 
     return new ModelTreeViewItem(); 
    } 

    protected override bool IsItemItsOwnContainerOverride(object item) 
    { 
     return item is ModelTreeViewItem; 
    } 
} 

在視圖模型,NeedsFocus被設置爲每當設置IsSelected時都爲假。

3

如果可以的話,我會添加此評論作爲評論,但爲什麼不只是讓TreeView處理焦點並使用TreeView.SelectedItem抽象地處理該項目。樹狀視圖始終能夠知道打字開始時選擇了哪個項目。如果選擇了一個項目,則TreeView處於焦點狀態,您可以將鍵盤命令傳送到該項目。

+0

謝謝約書亞。在我的情況下,我試圖最小化代碼,並讓用戶能夠使用輸入手勢(不必重新選擇節點)在樹視圖項上下文菜單上執行命令。目前,我正在擴展TreeViewItem以添加可用於MultiTrigger的Ne​​edsFocus屬性。 – 2011-05-11 16:42:07

相關問題