使用UpdateSourceTrigger绑定== LostFocus不会触发菜单或工具栏交互

时间:2011-04-12 06:33:48

标签: wpf data-binding

我注意到当用户激活菜单或工具栏时,与UpdateSourceTrigger==LostFocus的绑定不会更新。

这导致了一个不幸的情况,当用户从菜单或工具栏中选择“保存文件”时,用户所做的最后一次更改会丢失。

是否可以轻松解决此问题,或者是否必须将所有绑定更改为UpdateSourceTrigger=PropertyChanged

4 个答案:

答案 0 :(得分:11)

我知道这有点旧,但对于任何未来的读者,只需在ToolBar上设置以下内容就可以为我工作:

FocusManager.IsFocusScope="False"

答案 1 :(得分:3)

问题是,当菜单项被激活时,TextBox实际上失去焦点。因此,UpdateSourceTrigger LostFocus不会触发。根据您的(视图)模型,UpdateSourceTrigger PropertyChanged可能是也可能不是可行的解决方法。

对我来说,PropertyChanged不是一个选项(我需要在用户完成输入后验证数据,而不是之间),所以我通过调用此方法使用了一种解决方法在“保存文件”(或任何其他需要最新模型的菜单/工具栏条目)之前:

Public Shared Sub SaveFocusedTextBox()
    Dim focusedTextBox = TryCast(Keyboard.FocusedElement, TextBox)
    If focusedTextBox IsNot Nothing Then
        Dim be = focusedTextBox.GetBindingExpression(TextBox.TextProperty)
        If be IsNot Nothing Then be.UpdateSource()
    End If
End Sub

在此相关问题中可以找到针对此问题的其他一些方法:

(事实上,这个方法的功劳归功于rudigrobler在这个问题上的答案。)

答案 2 :(得分:3)

这对我很有用:

Private Sub MenuItem_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)

  Keyboard.FocusedElement.RaiseEvent(New RoutedEventArgs With {.RoutedEvent = LostFocusEvent})

End Sub

答案 3 :(得分:1)

虽然这里有有用的答案,但恕我直言,这并不是最好的方法。对我而言,最佳和次佳的选择是:

  1. 固定制表符顺序,以便在TextBox之前和之后的TextBox焦点范围内具有可聚焦元素。这是恕我直言的最佳选择,,但是只有在这是合理用户界面选择时,才应使用它。已经有自然会围绕TextBox的UI元素。
  2. 处理LostKeyboardFocus事件,然后显式更新绑定。请注意,尽管TextBox的焦点范围并没有失去焦点,但是不会总是丢失 keyboard 焦点。 / li>

第二个选项如下:

<TextBox Text="{Binding SomeProperty}" LostKeyboardFocus="TextBox_LostKeyboardFocus"/>
private void TextBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    BindingOperations.GetBindingExpression((DependencyObject)sender, TextBox.TextProperty)?.UpdateSource();
}

详细说明:

接受的答案将推迟更新绑定的源属性,直到发生某些已知需要该属性值的特定情况(例如执行“保存”命令)。不幸的是,这否定了MVVM范式的一个主要优点,即不必担心何时本身会发生,因为绑定引擎应该负责所有事情。

投票最高的答案对此有所改善,但是正如下面的注释所指出的那样,它仍然是特定于方案的解决方案。需要将其应用于UI中具有自己的焦点范围的每个元素。但更糟糕的是,它实际上修改了元素的UI行为,否则该行为与我们实际上关心的元素完全无关。良好的编码习惯意味着解决原始问题,而不是应用一些不相关的更改,而这些更改恰好具有对我们有利的副作用。

如果您可以简单地在用户界面中排列制表符的顺序,以便在与TextBox之后紧跟TextBox的焦点范围内有一个元素,那么恕我直言将是理想的选择解。这意味着用户界面可预测地为用户工作,并且代码与最简单的实现方式保持一致。

但这并不总是可能的。在某些情况下,自然制表符顺序要求TextBox紧跟MenuToolBar或其他本身是焦点范围的元素之前或之后。在这种情况下,对我而言,最直接的方法就是通过显式处理LostKeyboardFocus事件并在该事件发生时更新绑定源来修改绑定的“焦点丢失”行为。