C# 操纵WPF TextBox LostFocus事件和绑定的顺序
我有一个WPFC# 操纵WPF TextBox LostFocus事件和绑定的顺序,c#,wpf,mvvm,binding,C#,Wpf,Mvvm,Binding,我有一个WPF窗口,它表示一个数据编辑器。窗口的DataContext是一个可观察对象(它实现了INotifyPropertyChanged) 每个可观察对象的属性都绑定到窗口中的相应小部件上(对于数字类型,文本框,复选框,bool,等等) 我不想用“确定”和“取消”按钮来保存更改的属性;我希望在小部件失去焦点时,将底层数据持久化到可观察对象 为此,我处理了小部件的PreviewLostKeyboardFocus和LostFocus事件。我的撤销框架需要一个表示当前状态的可观察对象的副本和一个新
窗口
,它表示一个数据编辑器。窗口的DataContext
是一个可观察对象(它实现了INotifyPropertyChanged
)
每个可观察对象的属性都绑定到窗口中的相应小部件上(对于数字类型,文本框,复选框,bool
,等等)
我不想用“确定”和“取消”按钮来保存更改的属性;我希望在小部件失去焦点时,将底层数据持久化到可观察对象
为此,我处理了小部件的PreviewLostKeyboardFocus
和LostFocus
事件。我的撤销框架需要一个表示当前状态的可观察对象的副本和一个新状态的副本。PreviewLostKeyboardFocus
事件复制对象,而LostFocus
事件实际执行保存到数据库的操作
但我的问题是:在运行LostFocus
事件之后之前,字段上的绑定实际上不会更新底层的可观察对象。净效果是将TextBox
中的文本从“a”更改为“B”,将字段中的数据保留为“a”。将其从“A”改为“B”再改为“C”将保留“B”
我已经在事件处理程序和底层对象的setter中设置了断点。果然,PreviewLostKeyboardFocus
首先运行,然后是LostFocus
,最后是可观察对象的设置器
我想让它尽可能通用,因此虽然我可以告诉可观察对象使用键盘focuschangedeventargs
更新自己的属性,但我需要为每个字段使用单独的事件处理程序,并且可能有很多
在PreviewLostKeyboardFocus
和LostFocus
事件之间,是否有办法让绑定运行
XAML:
observeObject
类(setter):
谢谢 如果我正确理解您的问题,这可能是因为默认情况下,文本框
会在焦点丢失时更新源代码
解决此问题的一种方法是将文本框设置为PropertyChanged
<TextBox Text="{Binding ObjectProperty, UpdateSourceTrigger=PropertyChanged, StringFormat='{}{0:F5}'}"
我是在做研究的时候发现的。但我的印象是,修改每个人物都会引发事件。写入我的数据库可能会有很大的开销,同时也会使我的撤销堆栈过于细粒度。哦,我以为你在更新数据库时小部件失去了焦点。哦。。。等一下。我明白你的意思。是的,你说得对。让我试试。您可以将UpdateSourceTrigger设置为显式,并更新lost focus事件句柄中的属性。我认为UpdateSourceTrigger=PropertyChanged
对于我来说已经足够好了。我不喜欢它在每次按键时不断地更新底层对象,但我实在想不出什么理由来避免这种情况。这是用户思考的时间,所以性能真的不应该是一个问题。非常感谢。
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;
}
public class ObservableObject : INotifyPropertyChanged {
...
public Single ObjectProperty {
get {
return this._objectProperty;
}
set {
this._objectProperty = value;
RaisePropertyChanged("ObjectProperty");
}
}
}
<TextBox Text="{Binding ObjectProperty, UpdateSourceTrigger=PropertyChanged, StringFormat='{}{0:F5}'}"
<TextBox Text="{Binding ObjectProperty, UpdateSourceTrigger=Explicit, StringFormat='{}{0:F5}'}"
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
(sender as TextBox).GetBindingExpression(TextBox.TextProperty).UpdateSource();
}