WPF(C#) ItemsSource未更新:双向绑定值读取异常求助
解决WPF中ItemsSource绑定值不更新的问题
嘿,这个问题我太熟了!本质是WPF TwoWay绑定的默认更新时机在搞鬼——TextBox的TwoWay绑定默认只有在控件失去焦点时,才会把用户输入的新值同步回数据源。你弹出MessageBox的时候,TextBox会自动失去焦点,绑定的源更新触发了,所以能读到新值;没弹窗的话,TextBox还攥着焦点呢,数据源根本没接到新值,自然读的是旧的。
下面给你几个实用的解决办法,按需选就行:
1. 直接修改绑定的更新触发条件(最推荐)
在XAML的绑定里加上UpdateSourceTrigger=PropertyChanged,这样TextBox每输入一个字符就立刻同步到数据源,不用等失去焦点:
Text="{Binding Path=Infotext, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
这个方法最简单,一劳永逸,适合大多数场景。
2. 读取前手动触发绑定更新
如果不想全局修改触发方式,比如只需要在点击MenuItem的时候更新,可以在读取值之前,手动让绑定同步源:
// 先找到目标Ticket对象 var targetTicket = ((ObservableCollection<Ticket>)ic_Tickets.ItemsSource) .First(t => t.id == ((MenuItem)sender).Tag.ToString()); // 找到对应的TextBox容器,触发绑定更新 var container = ic_Tickets.ItemContainerGenerator.ContainerFromItem(targetTicket) as FrameworkElement; if (container != null) { var textBox = container.FindName("你的TextBox名字") as TextBox; if (textBox != null) { var bindingExpr = textBox.GetBindingExpression(TextBox.TextProperty); bindingExpr?.UpdateSource(); } } // 现在再读取就是新值了 string text = targetTicket.Infotext;
3. 用Dispatcher延迟读取(应对UI线程同步问题)
如果是UI线程的调度顺序导致的更新延迟,可以把读取操作放到后台优先级的Dispatcher队列里,让绑定有时间完成更新:
Application.Current.Dispatcher.BeginInvoke(new Action(() => { string text = ((ObservableCollection<Ticket>)ic_Tickets.ItemsSource) .Where(t => t.id == ((MenuItem)sender).Tag.ToString()) .First().Infotext; // 这里处理读取到的新值 }), DispatcherPriority.Background);
再补充一句:你遇到的MessageBox“生效”的原因很简单——MessageBox.Show会阻塞UI线程,同时强制TextBox失去焦点,WPF的绑定系统在控件失焦时会自动触发源更新,所以这时候数据源已经拿到新值了。但频繁弹框肯定不现实,上面的方法都能完美替代这个临时方案~
内容的提问来源于stack exchange,提问作者user3600403
相关产品推荐
相关产品推荐

