Есть ли способ, когда TextBox теряет фокус при нажатии на фон в Caliburn Micro? - PullRequest
0 голосов
/ 02 мая 2019

При попытке перестроить приложение WPF для использования Caliburn Micro я обнаружил, что TextBox не теряет фокус, когда вы щелкаете за его пределами.Есть ли исправление для такого поведения?

Я использую Caliburn Micro 3.2.0.Я пытался использовать более старые версии, но эта проблема сохраняется.

XAML:

<Window x:Class="WPFUI.Views.ShellView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPFUI.Views"
        xmlns:cal="http://www.caliburnproject.org"
        mc:Ignorable="d"
        Title="ShellView" Height="450" Width="800">
    <Grid>
        ...
        <WrapPanel>
            <TextBox x:Name="Name"  MinWidth="50"  
                     cal:Message.Attach="[Event LostFocus] = [Action Name_LostFocus()];
                     [Event PreviewTextInput] = [Action Name_PreviewTextInput($source, $eventArgs)]">
            </TextBox>
            ...
        </WrapPanel>
        ...
    </Grid>
</Window>

1 Ответ

0 голосов
/ 03 мая 2019

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

Например, предполагая, что ваш Xaml будет следующим

<Window x:Class="CM.WPFApp2019.Views.ShellView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:cal="http://www.caliburnproject.org"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CM.WPFApp2019.Views"
        xmlns:i = "http://schemas.microsoft.com/expression/2010/interactivity" 
        xmlns:behaviors="clr-namespace:CM.WPFApp2019.ViewModels"
        mc:Ignorable="d" Focusable="True"
        Title="ShellView" Height="450" Width="800">
    <i:Interaction.Behaviors>
        <behaviors:ClearFocusOnClickBehavior ElementToClearFocus="{Binding ElementName=Name}"/>
    </i:Interaction.Behaviors>
    <Grid>
        <WrapPanel>
            <TextBox x:Name="Name"  MinWidth="50"  Focusable="True"
                     cal:Message.Attach="[Event LostFocus] = [Action Name_LostFocus()];
                     [Event PreviewTextInput] = [Action Name_PreviewTextInput($source, $eventArgs)]">
            </TextBox>
        </WrapPanel>
    </Grid>
</Window>

Обратите внимание, что я добавил в окно поведение под названием ClearFocusOnClickBehavior. Также вы установили свойство Focusable Window в true.

Теперь вы можете определить поведение следующим образом

public class ClearFocusOnClickBehavior : Behavior<FrameworkElement>
    {
        public static readonly DependencyProperty ElementToClearFocusProperty = DependencyProperty.RegisterAttached("ElementToClearFocus", typeof(FrameworkElement), 
                                                                            typeof(ClearFocusOnClickBehavior), new UIPropertyMetadata());


        public FrameworkElement ElementToClearFocus
        {
            get { return (FrameworkElement)GetValue(ElementToClearFocusProperty); }
            set { SetValue(ElementToClearFocusProperty, value); }
        }
        protected override void OnAttached()
        {
            AssociatedObject.MouseDown += (sender, args) => 
            {
                FrameworkElement ctrl = ElementToClearFocus; 
                FrameworkElement parent = (FrameworkElement)ElementToClearFocus.Parent;

                while (parent != null && parent is IInputElement
                                  && !((IInputElement)parent).Focusable)
                {
                    parent = (FrameworkElement)parent.Parent;
                }

                DependencyObject scope = FocusManager.GetFocusScope(ElementToClearFocus); 
                FocusManager.SetFocusedElement(scope, parent as IInputElement);
            };
            base.OnAttached();
        }

    }

Поведение добавит событие MouseDown для связанного объекта, где вы сможете отследить Parent элемента управления ElementToClearFocus, который можно сфокусировать. В этом случае, поскольку вы установили окно как фокусируемое, оно получит фокус. Textbox в свою очередь теряет фокус и поднимает Name_LostFocus метод

...