web-dev-qa-db-ja.com

WPF-テキストボックスの外側をクリックしたときにフォーカスを削除する

WPFアプリケーションでフォーカスが通常とは少し異なる動作をするテキストボックスがいくつかあります。基本的に、テキストボックスがWebページで動作するように動作するようにします。つまり、テキストボックスの外側をクリックすると、フォーカスが失われます。そうするための最良の方法は何ですか?

答えがプログラムでフォーカスを削除することである場合、境界外のマウスクリックを検出する最良の方法は何ですか?私がクリックしている要素がフォーカスの新しい受信者になる場合はどうなりますか?

24
JacobJ

ウィンドウに新しいコントロールを追加するのではなく、Gridに名前を付けて、ウィンドウのMouseDownイベントに反応し、フォーカスをグリッド自体。このようなもの:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml" 
    Title="Window1" 
    Height="412" Width="569" 
    MouseDown="Window_MouseDown" 
    Name="window1">

    <Grid ShowGridLines="False" 
          Background="#01FFFFFF"
          KeyDown="Grid_KeyDown" 
          Name="grid1" 
          Focusable="True">

          <TextBox Width="120" Margin="117,61,0,0" 
                   Name="textBox1" 
                   VerticalAlignment="Top" 
                   HorizontalAlignment="Left"/>
    </Grid>
</Window>

コードビハインド:

private void window1_MouseDown(object sender, MouseButtonEventArgs e)
{
    grid1.Focus();
}
27

この問題を解決するより良い方法は、MouseDownイベントハンドラーをコードビハインド付きのウィンドウに追加することです。

private void window_MouseDown(object sender, MouseButtonEventArgs e)
{
    Keyboard.ClearFocus();
}
14
NightEagle

コードビハインドを回避するには、この動作を使用できます。

 public class ClearFocusOnClickBehavior : Behavior<FrameworkElement>
 {
    protected override void OnAttached()
    {
        AssociatedObject.MouseDown += AssociatedObject_MouseDown;
        base.OnAttached();
    }

    private static void AssociatedObject_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        Keyboard.ClearFocus();
    }

    protected override void OnDetaching()
    {
        AssociatedObject.MouseDown -= AssociatedObject_MouseDown;
    }
}

XAMLでの使用:

テキストボックスの外側にある要素で、クリックして追加することにフォーカスを解除してほしい:

    <i:Interaction.Behaviors>
        <behaviors:ClearFocusOnClickBehavior/>
    </i:Interaction.Behaviors>
3
shmoltz

私のために働いた別の方法は使用していた

Mouse.AddPreviewMouseDownOutsideCapturedElementHandler

たとえば、クリックすると、フォーカスされたTextBoxを表示して編集可能になるTextBlockがあるとします。次に、ユーザーがTextBoxの外側をクリックすると、再び非表示になります。方法は次のとおりです。

private void YourTextBlock_OnMouseDown(object sender, MouseButtonEventArgs e)
{
    YourTextBox.Visibility = Visibility.Visible;
    YourTextBox.Focus();
    CaptureMouse();
    Mouse.AddPreviewMouseDownOutsideCapturedElementHandler(this, OnMouseDownOutsideElement);
}

private void OnMouseDownOutsideElement(object sender, MouseButtonEventArgs e)
{
    Mouse.RemovePreviewMouseDownOutsideCapturedElementHandler(this, OnMouseDownOutsideElement);
    ReleaseMouseCapture();
    YourTextBox.Visibility = Visibility.Hidden;
}
3
Mr. Bungle

ネイティブWPFアプリケーションの反応で選択した回答を試しましたが、どのテキストボックスがフォーカスを失っていなかったため、テキストボックスの失われたフォーカスがトリガーされませんでした。次の解決策は私のために働きます。

マウスダウンイベントをウィンドウにバインドします。

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="412" Width="569" MouseDown="window_MouseDown" Name="window1" >
    <Grid ShowGridLines="False" KeyDown="Grid_KeyDown" Name="grid1" Focusable="True">
          <TextBox HorizontalAlignment="Left" Margin="117,61,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
    </Grid>
</Window>

そしてイベントは:

private void window_MouseDown(object sender, MouseButtonEventArgs e)
{
    TextBox textBox = Keyboard.FocusedElement as TextBox;
    if (textBox != null)
    {
        TraversalRequest tRequest = new TraversalRequest(FocusNavigationDirection.Next);
        textBox.MoveFocus(tRequest);
    }
}
2
Zaheer Ahmed

100%確実ではありませんが、コンテナ要素(Grid、StackPanelなど)でFocusableをtrueに設定すると、テキストボックスからフォーカスが外れるはずです。

2
Richard Szalay

フォーカスを取得できる要素をクリックすると、必要なものが得られます。たとえば、パネルがある場合は、パネルのmouseClickイベントを処理してニーズを達成するか、Richard Szalayのアドバイスを使用できます。

1
stukselbax

私は同様の問題に遭遇していましたが、ScrollViewerコントロールを私のtextboxesにラップすると、texboxの外側をクリックすると、すべてのtextboxが自動的にフォーカスを失います。

1
public class ClearFocusOnOutsideClickBehavior : Behavior<FrameworkElement>
{
    protected override void OnAttached()
    {

        AssociatedObject.GotFocus += AssociatedObjectOnGotFocus;
        AssociatedObject.LostFocus += AssociatedObjectOnLostFocus;
        base.OnAttached();
    }

    private void AssociatedObjectOnLostFocus(object sender, RoutedEventArgs e)
    {
        App.Current.MainWindow.MouseUp -= _paren_PreviewMouseUp;
    }

    private void AssociatedObjectOnGotFocus(object sender, RoutedEventArgs e)
    {
        App.Current.MainWindow.MouseUp += _paren_PreviewMouseUp;
    }

    private void _paren_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        Keyboard.ClearFocus();
    }

    protected override void OnDetaching()
    {
        AssociatedObject.GotFocus -= AssociatedObjectOnGotFocus;
        AssociatedObject.LostFocus -= AssociatedObjectOnLostFocus;
    }
}

XAMLでの使用:

<TextBox Height="30" Width="200">
            <i:Interaction.Behaviors>
                <behaviours:ClearFocusOnOutsideClickBehavior/>
            </i:Interaction.Behaviors>
 </TextBox>
0
Slavik Glodan

IsKeyboardFocusedChangedイベントを使用できます。

myTextBox.IsKeyboardFocusedChanged += myTextBox_IsKeyboardFocusedChanged;

private void SendFileCaptionTextBox_IsKeyboardFocusedChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    if (e.NewValue.ToString() == "True")
    {
        // it's focused
    }
    else
    {
        // it's not focused
    }
}    
0
Mayer Spitzer

コントロールのフォーカスを明示的に失うことはできません

代わりにフォーカスを他のコントロールに設定できます

**txt.Focusable=true;
label.focus();
Keyboard.Focus(txtPassword);**

これを試して

0
user3060599