如何将NotifyDataErrorInfo传递给自定义TextBox用户控件?
问题分析与解决方案
1. 自定义IntegerTextBox验证错误可视化异常
核心原因
自定义IntegerTextBox未正确继承全局TextBox的验证样式,且依赖属性绑定未配置完整的验证传递规则,导致默认红框模板生效、VM错误信息无法展示。
修复步骤
- 继承全局样式:在ResourceDictionary中为自定义控件添加基于修改后TextBox样式的专属样式,覆盖默认错误模板:
<Style TargetType="{x:Type local:IntegerTextBox}" BasedOn="{StaticResource {x:Type TextBox}}"> <Setter Property="Validation.ErrorTemplate"> <Setter.Value> <ControlTemplate> <StackPanel> <AdornedElementPlaceholder x:Name="placeholder"/> <TextBlock Text="{Binding [0].ErrorContent}" Foreground="Red" FontSize="10"/> </StackPanel> </ControlTemplate> </Setter.Value> </Setter> </Style> - 完善绑定配置:确保Value属性绑定开启验证传递:
<local:IntegerTextBox Value="{Binding TargetIntProperty, ValidatesOnNotifyDataErrors=True, NotifyOnValidationError=True, Mode=TwoWay}"/> - 同步属性验证:在自定义控件的Value依赖属性元数据中添加强制转换逻辑,避免非法值触发绑定错误:
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value), typeof(int), typeof(IntegerTextBox), new FrameworkPropertyMetadata(default(int), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValueChanged, CoerceValue)); private static object CoerceValue(DependencyObject d, object baseValue) { if (baseValue is int value && value < 1) return 1; return baseValue; } private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var textBox = d as IntegerTextBox; textBox.Text = e.NewValue.ToString(); }
2. CustomTextBox控制按键触发异常
核心原因
输入验证逻辑未区分编辑控制键(Backspace/Delete)与普通输入键,导致合法编辑操作被拦截,触发绑定转换异常。
修复步骤
- 区分控制键与输入键:在事件处理中允许Backspace/Delete、禁止Space,仅拦截非数字输入:
private void CustomTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e) { // 仅允许数字输入 e.Handled = !Regex.IsMatch(e.Text, @"^\d+$"); } private void CustomTextBox_PreviewKeyDown(object sender, KeyEventArgs e) { // 允许编辑键,禁止空格 if (e.Key == Key.Space) e.Handled = true; else if (e.Key is Key.Back or Key.Delete) e.Handled = false; } - 实时文本验证:在TextChanged事件中提前验证输入,避免非法文本触发绑定转换错误:
private void CustomTextBox_TextChanged(object sender, TextChangedEventArgs e) { var textBox = sender as TextBox; if (textBox == null) return; if (!int.TryParse(textBox.Text, out _) && !string.IsNullOrEmpty(textBox.Text)) { Validation.MarkInvalid( textBox.GetBindingExpression(TextBox.TextProperty), new ValidationError( new ExceptionValidationRule(), textBox.GetBindingExpression(TextBox.TextProperty), "输入必须是正整数", null)); } else { Validation.ClearInvalid(textBox.GetBindingExpression(TextBox.TextProperty)); } } - 绑定配置优化:为Text属性绑定添加异常验证开关:
<TextBox Text="{Binding TargetIntProperty, ValidatesOnExceptions=True, ValidatesOnNotifyDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
通用绑定注意事项
- 所有绑定需设置
Mode=TwoWay,确保视图与VM数据双向同步; - 开启
ValidatesOnNotifyDataErrors=True与NotifyOnValidationError=True,保证VM的INotifyDataErrorInfo错误能传递到视图; - 对于空文本场景,可在VM中处理默认值(如设为1),避免绑定转换时的空值异常。
内容的提问来源于stack exchange,提问作者karwenzman
相关产品推荐
相关产品推荐

