切换Tab页时WPF文本框验证状态丢失问题解决
WPF TabControl切换时恢复IDataErrorInfo验证指示器的解决方案
在WPF中使用TabControl对TextBox等输入控件分组,依赖ViewModel实现的IDataErrorInfo接口做用户输入验证时,会遇到一个问题:当输入内容无效时切换Tab页,返回原Tab后文本框的验证指示器会消失。
尝试过的无效方案
- 强制在Tab切换时触发验证逻辑
- 手动调用绑定的
UpdateSource()和UpdateTarget()方法 - 使用
Dispatcher.BeginInvoke延迟调度绑定更新操作
以上方法均无法恢复验证指示器的显示。
最终解决方案:实现附加属性RevalidateOnTabChangeBehavior
通过实现一个附加属性,在Tab切换时清除绑定的验证结果并重新更新绑定源,无需自定义控件样式即可恢复验证指示器。
附加属性代码实现
using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Media; public static class RevalidateOnTabChangeBehavior { public static readonly DependencyProperty AttachProperty = DependencyProperty.RegisterAttached( "Attach", typeof(bool), typeof(RevalidateOnTabChangeBehavior), new PropertyMetadata(false, OnAttachChanged)); public static bool GetAttach(DependencyObject obj) { return (bool)obj.GetValue(AttachProperty); } public static void SetAttach(DependencyObject obj, bool value) { obj.SetValue(AttachProperty, value); } private static void OnAttachChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is TabControl tabControl) { if ((bool)e.NewValue) { tabControl.SelectionChanged += OnTabSelectionChanged; } else { tabControl.SelectionChanged -= OnTabSelectionChanged; } } } private static void OnTabSelectionChanged(object sender, SelectionChangedEventArgs e) { if (e.AddedItems.Count > 0 && e.AddedItems[0] is TabItem selectedTab) { foreach (var element in FindVisualChildren<FrameworkElement>(selectedTab)) { var bindingExpression = element.GetBindingExpression(TextBox.TextProperty); if (bindingExpression != null) { Validation.ClearInvalid(bindingExpression); bindingExpression.UpdateSource(); } } } } private static IEnumerable<T> FindVisualChildren<T>(DependencyObject parent) where T : DependencyObject { if (parent == null) yield break; for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++) { var child = VisualTreeHelper.GetChild(parent, i); if (child is T target) { yield return target; } foreach (var nestedChild in FindVisualChildren<T>(child)) { yield return nestedChild; } } } }
使用方式
在XAML中给目标TabControl添加该附加属性即可:
<TabControl local:RevalidateOnTabChangeBehavior.Attach="True"> <!-- 你的Tab页内容 --> </TabControl>
核心逻辑是Tab切换后,遍历选中Tab内的所有TextBox控件,先清除之前的无效验证状态,再手动触发绑定源更新,重新激活IDataErrorInfo的验证逻辑,让验证指示器恢复显示。
内容的提问来源于stack exchange,提问作者J. Meyer
相关产品推荐
相关产品推荐

