Подтвердить что ты не робот

WPF - удаление фокуса при нажатии за пределами текстового поля

У меня есть несколько текстовых полей, в которых я бы хотел, чтобы фокус вел себя немного иначе, чем обычно для приложения WPF. В принципе, я бы хотел, чтобы они больше походили на текстовое поле на веб-странице. То есть, если я щелкнул где-нибудь за пределами текстового поля, он потеряет фокус. Каков наилучший способ сделать это?

Если ответ заключается в программном удалении фокуса, что лучший способ обнаружить Mouseclick за пределами границ? Что, если элемент, на который я нажимаю, станет новым получателем фокуса?

4b9b3361

Ответ 1

Вместо того, чтобы добавлять новый элемент управления в окно, я думаю, что вы должны дать вашей Grid имя и реагировать на событие MouseDown в вашем окне, перемещая фокус на саму Grid. Что-то вроде этого:

<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 window1_MouseDown(object sender, MouseButtonEventArgs e)
{
    grid1.Focus();
}

Ответ 2

Я думаю, лучший способ решить эту проблему - добавить обработчик событий MouseDown в окно с кодом:

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

Ответ 3

Другой способ, который работал у меня, заключался в использовании

Mouse.AddPreviewMouseDownOutsideCapturedElementHandler

Например, скажем, что у вас был TextBlock, который при щелчке должен стать редактируемым, показывая сфокусированный TextBox. Затем, когда пользователь щелкнет вне 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;
}

Ответ 4

Чтобы избежать кода позади, вы можете использовать это поведение

 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>

Ответ 5

Я не уверен на 100%, но если вы устанавливаете Focusable на true в элемент контейнера (Grid, StackPanel и т.д.), тогда он должен отвлечь фокус от текстового поля.

Ответ 6

Если вы нажмете на элемент, который может захватить фокус, вы получите то, что вам нужно. если, например, у вас есть панель, вы можете обрабатывать событие mouseClick панели для достижения ваших нужд или использовать рекомендации Ричарда Салаи.

Ответ 7

У меня была похожая проблема, но когда я обернул элемент управления ScrollViewer вокруг своих текстовых полей, все текстовые поля автоматически теряли фокус при щелчке в любом месте за пределами текстовых полей.

Ответ 8

вы не можете явно потерять фокус элемента управления

вы можете установить фокус на другое управление вместо

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

попробуйте это

Ответ 9

Вы можете использовать событие IsKeyboardFocusedChanged:

myTextBox.IsKeyboardFocusedChanged += myTextBox_IsKeyboardFocusedChanged;

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

Ответ 10

Я попробовал выбранный ответ в приложении 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);
    }
}

Ответ 11

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>