3

プログラムでキーボード フォーカスをツリー ビュー項目に設定しようとしています (特定の条件下で)。フォーカスを設定する 2 つの方法を試しましたが、どちらも にフォーカスを正常に取得できますが、TreeViewItemキーボード フォーカスが失われます。

ツリー ビューはビュー モデルにバインドされます。

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

TreeViewItem Selectedルーティング イベントを介してフォーカスを設定しようとしています。

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

にフォーカスを設定しようとしてTreeViewItemControlTemplateます:

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

これらのメソッドはどちらもフォーカスを取得しますが、キーボード フォーカスを失います (TreeViewItem.IsSelectionActiveは false)。ウィンドウ内の他の要素には、私が知ることができるフォーカスまたはキーボードフォーカスはありません(テストでは、フォーカスを取得できる別のパネルに読み取り専用テキストボックスが1つしかありません)。興味深いことに、(コメント アウトされた) が false の場所でキーボード フォーカスを取得できますMultiTriggerIsSelectionActive、もちろん、TreeViewItem常にキーボード フォーカスが強制されます。

キーボード フォーカスを取得する可能性を高める別の方法はありますか? また、キーボード フォーカスを取得できない条件にはどのようなものがありますか?

4

2 に答える 2

3

可能であれば、これをコメントとして追加しますが、TreeViewハンドルにフォーカスを設定し、を使用してアイテムを抽象的に操作してみませんかTreeView.SelectedItem。ツリービューは、入力が開始されたときにどのアイテムが選択されたかを常に知ることができます。アイテムが選択されている場合TreeViewは、フォーカスがあり、キーボードコマンドをアイテムにパイプできます。

于 2011-05-11T16:18:00.157 に答える
2

おそらくもっと良い方法がありますが、フォーカスを設定するときにトリガーする別のプロパティを持つTreeViewandを拡張することで、これを行う方法を見つけました。TreeViewItemNeedsFocus

ツリー ビュー:

    <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は、 が設定されるたびに false に設定さIsSelectedれます。

于 2011-05-11T20:03:42.333 に答える