c# - 处理 WPF TextBox LostFocus 事件和绑定(bind)的顺序

标签 c# wpf mvvm binding

我有一个代表数据编辑器的 WPF WindowWindowDataContext 是一个可观察对象(实现了 INotifyPropertyChanged)。

每个可观察对象的属性都绑定(bind)到 Window 中的适当小部件(TextBox 用于数字类型,CheckBox 用于 bool 等)。

我不想用“确定”和“取消”按钮来保存更改的属性;我希望在小部件失去焦点时将基础数据持久保存到可观察对象。

为此,我处理了小部件的 PreviewLostKeyboardFocusLostFocus 事件。我的撤消框架需要一份表示当前状态的可观察对象的副本,以及一份新状态的副本。 PreviewLostKeyboardFocus 事件复制对象,LostFocus 事件实际执行保存到数据库。

但我的问题是:在 LostFocus 事件运行之前,字段上的 Binding 实际上不会更新底层可观察对象。最终效果是将 TextBox 中的文本从“A”更改为“B”会将字段中的数据保留为“A”。将其从“A”更改为“B”再到“C”将保留“B”。

我已经在事件处理程序和底层对象的 setter 中放置了断点。果然,PreviewLostKeyboardFocus 首先运行,然后是 LostFocus,最后是可观察对象的 setter。

我想让它尽可能通用,所以虽然我可以告诉可观察对象使用 KeyboardFocusChangedEventArgs 更新它自己的属性,但我需要为每个字段单独的事件处理程序,并且可能有很多。

有什么方法可以让绑定(bind)PreviewLostKeyboardFocusLostFocus 事件之间运行?

XAML:

<TextBox Text="{Binding ObjectProperty, StringFormat='{}{0:F5}'}" LostFocus="PersistentTextBox_LostFocus" PreviewLostKeyboardFocus="PersistentTextBox_PreviewLostKeyboardFocus" />

代码隐藏中的事件处理程序:

private void PersistentTextBox_LostFocus(object sender, RoutedEventArgs e) {
    this.ObservableObject.PersistChanges(this.tempObservableObject);
}

private void PersistentTextBox_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) {
    this.tempObservableObject = this.ObservableObject;
}

ObservableObject 类(setter):

public class ObservableObject : INotifyPropertyChanged {
    ...
    public Single ObjectProperty {
        get {
            return this._objectProperty;
        }
        set {
            this._objectProperty = value;
            RaisePropertyChanged("ObjectProperty");
        }
    }
}

谢谢!

最佳答案

如果我正确理解您的问题,这可能是因为默认情况下 TextBox 会在失去焦点时更新 Source

解决此问题的一种方法是将 TextBox UpdateSourceTrigger 设置为 PropertyChanged

<TextBox Text="{Binding ObjectProperty, UpdateSourceTrigger=PropertyChanged, StringFormat='{}{0:F5}'}" 

这将允许在 TextBox 中发生更改后立即更新底层可观察对象,然后您可以在小部件失去焦点事件中保留更改

或者您可以将 UpdateSourceTrigger 设置为 Explicit 并更新 LostFocus 处理程序中的 Source。

 <TextBox Text="{Binding ObjectProperty, UpdateSourceTrigger=Explicit, StringFormat='{}{0:F5}'}" 

    private void TextBox_LostFocus(object sender, RoutedEventArgs e)
    {
       (sender as TextBox).GetBindingExpression(TextBox.TextProperty).UpdateSource();
    }

关于c# - 处理 WPF TextBox LostFocus 事件和绑定(bind)的顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14881804/

相关文章:

两个协变接口(interface)的 C# 协变问题

c# - Web API 只允许单个异步任务

android - 如何在存储库类MVVM中使用Firebase身份验证监听器?

c# - 如何使用 MVVM Light 检测 TextBox 中的按键

c# - 在 lambda 中使用变量

c# - 如何将 visual studio 2010 SP1 解决方案转换为 visual studio 2012 解决方案?

c# - Caliburn Micro Conductor.Collection.AllActive 不工作

c# - Uri 为 WPF 样式 uri 抛出无效端口

c# - InputBinding 和 WebBrowser 控件

Wpf 内容控制