单击某些其他控件时不会引发TextBox LostFocus

Jus*_*tin 8 wpf focus toolbar lost-focus

在下面的简单WPF应用程序中,a TextBox设置为在焦点从该控件中丢失时更新属性,如下所示

<DockPanel>
    <ToolBar DockPanel.Dock="Top">
        <Button>Test</Button>
    </ToolBar>
    <TextBox Text="{Binding MyString}" />
</DockPanel>

public MainWindow()
{
    InitializeComponent();
    DataContext = this;
}

public string MyString
{
    get { return _myString; }
    set { _myString = value; }
}
Run Code Online (Sandbox Code Playgroud)

但是,当我运行此应用程序时,在文本框中输入一些文本,然后单击"测试"按钮,我的MyString属性上的断点不会引发,也不会引发该FocusLost事件的任何事件处理程序.仅当通过某些其他方式(例如窗口关闭)从控件丢失焦点时才会引发这些事件.

这对我们造成了问题,因为实际上"测试"按钮包含依赖于MyString正在更新的属性的逻辑.

FocusLost当我单击"测试"按钮时,如何确保正确引发事件并更新绑定?看起来问题是由于使用而导致的问题ToolBar,因为用ToolBar标准按钮替换不会导致这种行为.

Jus*_*tin 5

在这种情况下,文本框实际上并没有失去逻辑焦点,因此永远不会引发事件 - 本质上我实际上想要该LostKeyboardFocus事件,而不是LostFocus触发更新的事件。

这个问题类似于WPF:数据绑定在选择新标签的TabControl不提交更改,有是它的一个微软连接项目在这里与一些可能的解决方案,但我解决了这个使用附加属性,像这样。

public static readonly DependencyProperty BindOnLostKeyboardFocusProperty =
    DependencyProperty.RegisterAttached("BindOnLostKeyboardFocus", typeof(bool), typeof(MainWindow), new PropertyMetadata(default(bool), BindOnLostKeyboardFocusChanged));

private static void BindOnLostKeyboardFocusChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
    var control = o as UIElement;
    if (control != null)
    {
        if ((bool) e.NewValue)
        {
            control.AddHandler(LostKeyboardFocusEvent, new RoutedEventHandler(ControlLostKeyboardFocus));
        }
        else
        {
            control.RemoveHandler(LostKeyboardFocusEvent, new RoutedEventHandler(ControlLostKeyboardFocus));
        }
    }
}

private static void ControlLostKeyboardFocus(object sender, RoutedEventArgs e)
{
    var control = (UIElement)sender;
    control.RaiseEvent(new RoutedEventArgs(LostFocusEvent));
}
Run Code Online (Sandbox Code Playgroud)

这只是意味着每当LostKeyboardFocus为该控件引发时,它都会继续并引发一个额外的LostFocus事件,导致绑定更新。它像这样使用

<TextBox Text="{Binding Test}" LostKeyboardFocus="UIElement_OnLostKeyboardFocus" local:MainWindow.BindOnLostKeyboardFocus="True" />
Run Code Online (Sandbox Code Playgroud)