WPF:プログラムによってTextBoxからフォーカスを削除する方法


95

単純な(少なくともそうだと思っていた)動作をWPFに追加したいTextBox

ユーザーがEscapeキーを押しTextBoxたときに、ユーザーが編集を開始したときのテキストをユーザーが編集できるようにしたいTextBox。また、フォーカスをから削除したい。

編集の最初に持っていた値のテキストを設定することに問題はありません。

問題は、要素のフォーカスを削除することです。フォーカスを他のコンポーネントに移動したくありませんTextBox。フォーカスを失いたいだけです。フォーカスTextBoxを失うには、フォーカスを設定するために非表示の要素が必要ですか?

回答:


152

.NET Framework 4では Keyboard.ClearFocus();


1
これがまさに今晩私が探していたものでした!
Josh

9
これは常にフォーカスをクリアするとは限りませんKeyboard.ClearFocus()。どこかクリックした後にコードビハインドから実行したときに、ListBox内のAutoCompleteTextBoxがフォーカスを失わないという問題があります。
ANeves、2015

3
ClearFocusGotFocus他のコントロールに対してはまだ発生しているが、最近フォーカスされたコントロールに対しては発生しない原因となります。たとえば、これは私のカスタムオンスクリーンキーボードにとって大きな問題です。それはキャレットを消します、それはおそらく「キーボードフォーカス」が伴うすべてです。たぶん、「マウスフォーカス」のようなものにもっと興味があります。
Grault

2
Graultに感謝します。同じ問題が発生しました。私が思いついた最善の方法は、でフォーカスを他のコントロールに移動することother.Focus()です。
Tor Klingberg 2016

7
@Graultこれは、キーボードフォーカスのみをクリアし、論理フォーカス(GotFocusイベントに発生するもの)はクリアしません。プログラムには常に論理的な焦点があるものがあります。LostKeyboardFocusキーボードフォーカスをクリアする前に、イベントを使用するか、別の要素にフォーカスを移動します(論理フォーカスも一緒に移動します)。
Chirimorin

54

私が使用しているコード:

// Move to a parent that can take focus
FrameworkElement parent = (FrameworkElement)textBox.Parent;
while (parent != null && parent is IInputElement && !((IInputElement)parent).Focusable)
{
    parent = (FrameworkElement)parent.Parent;
}

DependencyObject scope = FocusManager.GetFocusScope(textBox);
FocusManager.SetFocusedElement(scope, parent as IInputElement);

2
このコードは素晴らしいです。Keyboard.ClearFocus()には意図しない副作用がいくつかあります
パトリック

条件!((IInputElement)parent).Focusableに「!」がある理由 前に?親がフォーカス可能である場合、この条件は真ではありませんか?
Mert Akcakaya 2012年

Mert-確かではありませんが、この投稿を閲覧するだけで、その条件がtrueになるまでループを継続することで表示されます。これにより、最初のフォーカス可能なアイテムがループを終了します。
jpierson 2012年

4
@patrick、副作用を意図しない?関連する例を挙げていただけますか?
ANeves 2014

1
これは素晴らしいソリューションです。Keyboard.ClearFocus()にも問題がありました。モーダルウィンドウ内のTextBoxでClearFocus()を実行すると、TextBoxとWindowの両方がフォーカスを失います。つまり、KeyDownイベントはウィンドウに移動しません。フォーカスを親(ウィンドウの場合もあります)に変更するように変更することにより、将来のKeyDownイベントは失われません。私の実際の例では、「Key.Escape」を探し、Close()を呼び出すウィンドウがあります。ClearFocus()をどこかで実行すると、これは機能しなくなります。
Denis P

19

パーティーには少し遅れましたが、それは私にとって役に立ちましたので、ここに行きます。

.Net 3.0以降、私のためにトリックを実行FrameworkElementするMoveFocus関数があります。



「このメソッドの戻り値を確認してください。トラバーサルがコントロールの構成で定義されたタブストップに達し、トラバーサルリクエストがラップをリクエストしなかった場合、falseの戻り値が返される可能性があります。」- msdn.microsoft.com/en-us/library/...
aderesh

13

上記の答えはどれもうまくいきませんでしたし、受け入れられた答えはキーボードフォーカスでしかうまくいきませんでした。

// Kill logical focus
FocusManager.SetFocusedElement(FocusManager.GetFocusScope(textBox), null);
// Kill keyboard focus
Keyboard.ClearFocus();

論理的およびキーボードフォーカスの両方を強制終了します。


9

フォーカス可能な祖先にフォーカスを設定できます。このコードは、テキストボックスがテンプレート内にあり、同じテンプレート内にフォーカス可能な祖先がない場合でも機能します。

DependencyObject ancestor = textbox.Parent;
while (ancestor != null)
{
    var element = ancestor as UIElement;
    if (element != null && element.Focusable)
    {
        element.Focus();
        break;
    }

    ancestor = VisualTreeHelper.GetParent(ancestor);
}

6

申し訳ありませんが、フォーカスを完全に削除することはできません。ウィンドウ内の何かが常にフォーカスされます。


2

Windows Phoneの開発では、私はやった Focus()this.Focus()PhoneApplicationPage、それが魅力のように働きました。


1

私にとっては、特にLostFocusバインディングで使用する場合は、かなり注意が必要です。ただし、私の回避策は、空のラベルを追加してそれに焦点を当てることです。

<Label Name="ResetFocusArea" Focusable="True" FocusVisualStyle="{x:Null}" />

...

OnKeyDown(object sender, RoutedEventArgs e)
{
  //if is Esc
  ResetFocusArea.Focus();
}

0

私の回答は上記の質問に直接対処するものではありませんが、その言葉遣いがプログラムからフォーカスを取り除くことに関する「質問」になったと感じています。これが必要になる一般的なシナリオは、ユーザーがウィンドウなどのルートコントロールの背景を左クリックしてフォーカスをクリアできるようにすることです。

そのため、これを実現するために、動的に作成されたコントロール(私の場合は空のラベル)にフォーカスを切り替えるアタッチされた動作を作成できます。ダミーラベルを追加できるパネルを見つけるために子を反復するので、ウィンドウなどの最上位の要素でこの動作を使用することをお勧めします。

public class LoseFocusOnLeftClick : Behavior<FrameworkElement>
{
    private readonly MouseBinding _leftClick;
    private readonly Label _emptyControl = new Label() { Focusable = true, HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Top };

    public LoseFocusOnLeftClick()
    {
        _leftClick = new MouseBinding(new RelayCommand(LoseFocus), new MouseGesture(MouseAction.LeftClick));
    }

    protected override void OnAttached()
    {
        AssociatedObject.InputBindings.Add(_leftClick);
        AssociatedObject.Loaded += AssociatedObject_Loaded;
    }        

    protected override void OnDetaching()
    {
        AssociatedObject.InputBindings.Remove(_leftClick);
        AssociatedObject.Loaded -= AssociatedObject_Loaded;
    }

    private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
    {
        AssociatedObject.Loaded -= AssociatedObject_Loaded;

        AttachEmptyControl();
    }

    private void AttachEmptyControl()
    {            
        DependencyObject currentElement = AssociatedObject;
        while (!(currentElement is Panel))
        {
            currentElement = VisualTreeHelper.GetChild(currentElement, 0);
        }

        ((Panel)currentElement).Children.Add(_emptyControl);
    }

    private void LoseFocus()
    {            
        _emptyControl.Focus();
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.