You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 20:24:50