0

次の構造のアプリケーションで (キーボード) フォーカスを適切に機能させようとしています。

ItemsControl
  DataTemplate for Item
    ContentControl
      DataTemplate for Content (multiple, depending on type)
        Some container
          Different controls (mainly textbox or OK button should have focus)

各コンテンツ テンプレート (「いくつかのコンテナー」) のルートでFocusManager.FocusedElement、テンプレート内の 1 つのコントロールに設定します。ItemsControl 内のすべての項目のうち、実際に表示されるのは ContentControls の 1 つだけです (「現在の」項目)。したがって、基本的には、最初のものを表示します。その中の [OK] ボタンにフォーカスがあり、ユーザーは Enter キーを押して確認できます。次に、これが非表示になり、次のコントロールが表示され、そのメイン コントロール (テキスト ボックスなど) にフォーカスがあり、ユーザーは Enter キーを押して確認できます (テキスト ボックスに入力して項目を確認するための小さなイベント処理)。

すべてが完了したら、ユーザーはツールバーのボタンをクリックして最初からやり直すことができ、最初の ContentControl が再び表示されます。しかし、今回はピントが合っていません。誰がフォーカスを持っているのかわからないので、最初のように機能させたいと思います。表示されたばかりの ContentControl (破線で表示されます) にフォーカスを設定しようとしましたが、その子にフォーカスが設定されません。どのデータ テンプレートが選択されているかわからないので (まあ、特別なコードを書かないとだめです)、手動でフォーカスを設定したり、子へのバインドを介してフォーカスを設定したりすることはできません。この時点で簡単なことを見逃しているのでしょうか?

一方、ユーザーがアクティブな ContentControl ボタンまたはテキスト ボックスを手動でクリックすると、Enter キーを押して確認できますが、次のアイテムではなく、ItemsControl にフォーカスがあるように見えます。私はこの焦点について頭を悩ませることができません。簡単な解決策はありますか?ContentControl からツリーをトラバースして正しいデータ テンプレートを取得するコードを作成する必要がありますか? そして、データ テンプレートまたは FocusedElement として設定されているコントロールに何らかの形でフォーカスすることができますか、それともデータ テンプレートごとに個別にコードを記述する必要がありますか?

4

1 に答える 1

0

必要に応じて ViewModel から要素をフォーカスするためにトリガーできるアクションを実装する必要があります。このコードを試してください:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Interactivity;
using System.Windows;

namespace Behaviors
{
    /// <summary>
    /// Action to focus target element, if invoked when target is not yet specified, will focus once the target is set
    /// </summary>
    public class FocusAction : TargetedTriggerAction<DependencyObject>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
        }
        protected override void OnDetaching()
        {
            base.OnDetaching();
        }
        protected override void Invoke(object parameter)
        {
            if (Target is UIElement)
            {
                if(!((UIElement)Target).IsKeyboardFocusWithin)
                    ((UIElement)Target).Focus();
            }
            else
                invokeOnConnect = true;
        }
        private bool invokeOnConnect = false;
        protected override void OnTargetChanged(DependencyObject oldTarget, DependencyObject newTarget)
        {
            base.OnTargetChanged(oldTarget, newTarget);
            if (invokeOnConnect)
            {
                invokeOnConnect = false;
                Invoke(null);
            }
        }
    }
}

そしてWPFで:

<DockPanel>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <nuib:FocusAction TargetName="title"/>
            </i:EventTrigger>
        <TextBlock x:Name="title"/>
</DockPanel>

名前空間は次のとおりです。

xmlns:nuib="clr-namespace:Behaviors;assembly=Nui" // for Action class
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" // .net library for interactivity
于 2013-02-06T08:02:24.933 に答える