【问题标题】:WPF: Changes to textbox with focus aren't committed until after the Closing event firesWPF:直到关闭事件触发后才会提交对具有焦点的文本框的更改
【发布时间】:2010-09-18 09:08:07
【问题描述】:

我有一个用于编辑数据库信息的 WPF 窗口,它使用实体框架对象表示。当用户关闭窗口时,我想在 Closing 事件中注意信息是否已更改,并显示一个消息框,提供将更改保存到数据库。

不幸的是,在编辑失去焦点之前,对当前焦点编辑的更改不会分配给绑定源,这发生在处理 Closing 事件之后的某个时刻。

理想情况下,应该有一个例程提交视图层次结构中的所有更改,我可以在检查我的实体是否已被修改之前调用该例程。我还查找了有关以编程方式清除带有焦点的控件中的焦点的信息,但不知道该怎么做。

我的问题是,这通常是如何处理的?

【问题讨论】:

标签: wpf data-binding


【解决方案1】:

这应该让你非常接近:



private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
    ForceDataValidation();
}


private static void ForceDataValidation()
{
    TextBox textBox = Keyboard.FocusedElement as TextBox;

    if (textBox != null)
    {
        BindingExpression be = textBox.GetBindingExpression(TextBox.TextProperty);
        if (be != null && !textBox.IsReadOnly && textBox.IsEnabled)
        {
            be.UpdateSource();
        }
    }

}


【讨论】:

  • 我还检查了文本框是否有编辑:if ((textBox != null) && (textBox.CanUndo)) {...}
【解决方案2】:

还可以查看this 帖子中的建议

【讨论】:

    【解决方案3】:

    最简单的方法是将焦点设置在某处。 您可以立即重新设置焦点,但将焦点设置在任何位置都会触发任何类型控件上的 LostFocus-Event 并使其更新其内容:

    IInputElement x = System.Windows.Input.Keyboard.FocusedElement;
    DummyField.Focus();
    x.Focus();
    

    另一种方法是获取焦点元素,从焦点元素中获取绑定元素,然后手动触发更新。 TextBox 和 ComboBox 的示例(您需要添加需要支持的任何控件类型):

    TextBox t = Keyboard.FocusedElement as TextBox;
    if ((t != null) && (t.GetBindingExpression(TextBox.TextProperty) != null))
      t.GetBindingExpression(TextBox.TextProperty).UpdateSource();
    ComboBox c = Keyboard.FocusedElement as ComboBox;
    if ((c != null) && (c.GetBindingExpression(ComboBox.TextProperty) != null))
      c.GetBindingExpression(ComboBox.TextProperty).UpdateSource();
    

    【讨论】:

      【解决方案4】:

      假设 tab 序列中有多个控件,下面的解决方案看起来是完整和通用的(只是剪切和粘贴)...

      Control currentControl = System.Windows.Input.Keyboard.FocusedElement as Control;
      
      if (currentControl != null)
      {
          // Force focus away from the current control to update its binding source.
          currentControl.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
          currentControl.Focus();
      }
      

      【讨论】:

        【解决方案5】:

        在 WPF 中,您可以更改 Binding 以在修改时更新源,而不是在失去焦点时更新。这是通过将UpdateSourceTrigger 属性设置为PropertyChanged 来完成的:

        Value="{Binding Path=MyProperty, UpdateSourceTrigger=PropertyChanged}"
        

        【讨论】:

        • 最佳答案,因为它是纯 MVVM,不涉及搞乱事件。然而令人不满意的是,这不是默认触发器,因为它对我来说似乎是最直观的双向绑定行为......
        • 当您有一个转换器在离开键盘焦点后更正值时,这将不起作用。例如,当我的 ConvertBack 从数字中删除尾随零(将“5.80”转换为“5.8”)时,我将无法写入“5.801”,因为转换器阻止我写入零。 PropertyChanged 后,TextBox 中的文本将从“5.80”变为“5.8”。
        【解决方案6】:

        也许你需要从当前元素中移除焦点

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            FocusManager.SetFocusedElement(this, null);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-01-10
          相关资源
          最近更新 更多