我有一个代表数据编辑器的WPF Window
。 DataContext
的{{1}}是一个可观察对象(实现Window
)。
每个可观察对象的属性都绑定到INotifyPropertyChanged
中的相应窗口小部件(数字类型为Window
,TextBox
为CheckBox
等)。
我不希望使用“确定”和“取消”按钮来保留更改的属性;我希望当小部件失去焦点时,底层数据会持久保存到可观察对象。
为此,我处理了小部件的bool
和PreviewLostKeyboardFocus
事件。我的undo框架需要一个代表当前状态的observable对象的副本,以及一个新状态的副本。 LostFocus
事件生成对象的副本,PreviewLostKeyboardFocus
事件实际执行保存到数据库。
但我的问题是:在运行LostFocus
事件 之后,字段上的绑定实际上并不会更新基础可观察对象。实际效果是将LostFocus
中的文本从“A”更改为“B”将使字段中的数据保持为“A”。将其从“A”更改为“B”再变为“C”将持续存在“B”。
我在事件处理程序和底层对象的setter中放置了断点。果然,TextBox
首先运行,然后运行PreviewLostKeyboardFocus
,最后运行可观察对象的设置器。
我想让它尽可能通用,所以虽然我可以告诉可观察对象使用LostFocus
更新自己的属性,但我需要为每个字段分别设置事件处理程序,并且可能会有相当的一些。
有没有办法让KeyboardFocusChangedEventArgs
在Binding
和PreviewLostKeyboardFocus
事件之间运行?
XAML:
LostFocus
代码背后的事件处理程序:
<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;
}
class(setter):
ObservableObject
谢谢!
答案 0 :(得分:5)
如果我正确理解您的问题,可能是因为默认情况下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();
}