WPF中如何让TextBox的UpdateSourceTrigger更新先于LostFocus事件执行?
解决WPF中TextBox LostFocus事件前先更新绑定源的问题
你的问题核心是:绑定设置了UpdateSourceTrigger=Explicit导致LostFocus事件触发时,DescontoTotal还没同步文本框的输入值,但又不能用PropertyChanged(因为转换器需要输入完成后再格式化)。这里有个简单直接的解决方案,完全贴合你的需求:
方法:在自定义LostFocus事件开头手动触发绑定源更新
既然你用了Explicit触发模式,我们只需要在执行计算逻辑前,手动调用绑定的UpdateSource()方法,强制把文本框的最新值同步到DescontoTotal上。修改你的事件处理代码如下:
private void txtTotaisNfe_LostFocus(object sender, RoutedEventArgs e) { // 先手动同步绑定源,确保DescontoTotal是最新值 var textBox = sender as TextBox; if (textBox != null) { var bindingExpr = textBox.GetBindingExpression(TextBox.TextProperty); bindingExpr?.UpdateSource(); } // 现在可以放心使用更新后的DescontoTotal进行计算了 foreach (var item in _lsProdutos) { item.Desconto = (ThisDataContext.DescontoTotal / ThisDataContext.TotalProdutos * item.ValorProduto).Round(); } }
为什么这个方法可行?
- 保留转换器逻辑:
ConvertBack依然只会在你调用UpdateSource()时执行(也就是LostFocus事件内),完全满足你「输入完整值后再转换为两位小数」的要求,不会像PropertyChanged那样每输入一个字符就触发转换。 - 确保数据同步:手动更新放在事件逻辑最开头,保证后续计算用的是文本框的最新输入值,解决了之前
DescontoTotal未更新的问题。 - 改动最小:不需要修改XAML的绑定设置,只需要在事件处理里加几行代码,成本很低。
备选方案:调整事件执行顺序(更复杂)
如果你不想手动调用UpdateSource(),也可以通过调整事件注册顺序,让自定义的LostFocus处理逻辑在WPF默认的绑定更新之后执行。不过这种方法需要在代码后台注册事件,而不是在XAML里直接绑定:
public YourWindow() { InitializeComponent(); // 注册LostFocus事件,指定让自定义处理程序在默认逻辑之后执行 txtTotaisNfe.AddHandler(TextBox.LostFocusEvent, new RoutedEventHandler(txtTotaisNfe_LostFocus), handledEventsToo: false); }
然后把XAML里的LostFocus="txtTotaisNfe_LostFocus"去掉。不过这种方法依赖WPF的路由事件执行顺序,不如第一种手动更新的方式直观可控,所以更推荐第一种方案。
内容的提问来源于stack exchange,提问作者Renan Valentim
相关产品推荐
相关产品推荐

