简体   繁体   English

在Caliburn Micro中单击背景时,TextBox是否有办法失去焦点?

[英]Is there a way a TextBox loses focus when clicking on the background in Caliburn Micro?

When trying to rebuild a WPF Application to use Caliburn Micro I experienced that a TextBox does not loose focus when you click outside of it. 当尝试重建WPF应用程序以使用Caliburn Micro时,我发现当您在其外部单击时, TextBox不会失去焦点。 Is there a fix for that behaviour? 这种行为有解决方法吗?

I am using Caliburn Micro 3.2.0. 我使用的是Caliburn Micro 3.2.0。 I tried using older versions but this problem persits. 我尝试使用旧版本,但这个问题仍然存在。

XAML: 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>

I assume this is a case where you do not have any other Element in the Window other than the Textbox, which is why it cannot lose focus. 我假设这是一种情况,除了文本框之外,窗口中没有任何其他元素,这就是它不能失去焦点的原因。 One way to achieve this is to make the Window Focusable and setting Focus to it using a behavior. 实现此目的的一种方法是使Window Focusable并使用行为将Focus设置为它。

For Example, assuming your Xaml to be as follows 例如,假设您的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>

Please note I have added a Behavior called ClearFocusOnClickBehavior to the Window. 请注意我已经向Window添加了一个名为ClearFocusOnClickBehavior的行为。 Also you have set the Focusable Property of Window to be true. 您还将Window的Focusable属性设置为true。

Now you can define the behavior as follows 现在您可以按如下方式定义行为

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();
        }

    }

The Behavior would add a MouseDown event for the associated object, where you could trace the Parent of the ElementToClearFocus Control which can be Focused. 行为将为关联对象添加MouseDown事件,您可以在其中跟踪可以聚焦的ElementToClearFocus控件的Parent In this case, since you have set the Window as focusable, it would receive the Focus. 在这种情况下,由于您已将Window设置为可聚焦,因此它将接收Focus。 The Textbox in turn loses the focus and raises the Name_LostFocus method Textbox依次失去焦点并引发Name_LostFocus方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM