王彦为

聚沙成塔
  1. 首页
  2. WPF
  3. 正文

WPF的TextBox输入验证之ValidationRule验证

2016-12-22 63967点热度 85人点赞 6条评论

接上一篇文章《WPF的TextBox输入验证之Exception验证》,该文章继续讲述TextBox输入验证的方法,利用ValidationRule验证。

效果



初步方案

// 第一步,修改TextBox的Validation.ErrorTemplate
// 修改方法参考文章《WPF的TextBox输入验证之Exception验证》或下载源码

// 第二步,写验证规则
using System.Windows.Controls;
class AgeRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        int age;
        if (!int.TryParse(value.ToString(), out age))
        {
            return new ValidationResult(false, "Invalid number format");
        }
        if (age > 150 || age < 0)
        {
            return new ValidationResult(false, "Age should between 0 and 150");
        }
        return ValidationResult.ValidResult;
    }
}
// 第三步,写XAML布局
<TextBox Grid.Row="1" Grid.Column="1" Name="txtAge" >
    <TextBox.Text>
        <Binding Path="Age" UpdateSourceTrigger="PropertyChanged" >
            <Binding.ValidationRules>
                <local:NumberRule/>
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

// 第四步,提交时验证所有控件是否满足要求
private void btnSubmit_Click(object sender, RoutedEventArgs e)
{
    if (!Validation.GetHasError(txtName) && !Validation.GetHasError(txtAge))
    {
        MessageBox.Show("Verificate successfully.");
    }
    else
    {
        MessageBox.Show("Please input correct data in red textbox","Warning", MessageBoxButton.OK, MessageBoxImage.Warning);
    }
}

该方案有两个的缺点:一、提交表单时需要验证所有控件是否满足要求,所以所有TextBox都需要命名;二、每个属性都需要写一个验证类,工作量较大。针对第一点我们查找出页面中所有的TextBox控件,然后进行遍历判断,代码如下:

private void Submit()
{
    List<TextBox> texboxs = new List<TextBox>();
    GetChildrenObject(this, ref texboxs, true);
    foreach (var texbox in texboxs)
    {
        if (Validation.GetHasError(texbox))
        {
            MessageBox.Show("Please input correct data in red textbox", "Warning", MessageBoxButton.OK, MessageBoxImage.Warning);
            return;
        }
    }
    MessageBox.Show("Verificate successfully.");
}
private void GetChildrenObject<T>(DependencyObject obj, ref List<T> list, bool isDeepSearch) where T : FrameworkElement
{
    DependencyObject child = null;
    for (var i = 0; i <= VisualTreeHelper.GetChildrenCount(obj) - 1; i++)
    {
        child = VisualTreeHelper.GetChild(obj, i);

        if (child is T)
        {
            list.Add((T)child);
        }
        else
        {
            if (isDeepSearch)
            {
                GetChildrenObject(child, ref list, true);
            }
        }
    }
}

针对第二点,我们可以抽象出一个通用的验证类,例如年龄的范围是0-150岁,身高的的范围是40-300cm,那么我们抽象出一个数据范围验证类,在Xaml中设置最大值和最小值,改进方案如下。

改进方案

<TextBox Grid.Row="1" Grid.Column="1" Name="txtAge" >
    <TextBox.Text>
        <Binding Path="Age" UpdateSourceTrigger="PropertyChanged" >
            <Binding.ValidationRules>
                <local:NumberRule Minimum="0" Maximum="150"/>
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>
<TextBox Grid.Row="1" Grid.Column="1" Name="txtHeight" >
    <TextBox.Text>
        <Binding Path="Height" UpdateSourceTrigger="PropertyChanged" >
            <Binding.ValidationRules>
                <local:NumberRule Minimum="40" Maximum="300" ErrorMessage="身高范围[40,300]cm"/>
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

// 数字验证类
class NumberRule : ValidationRule
{
    // 添加ErrorMessage字段,用于自定义错误提示
    public string ErrorMessage { get; set; }
    public double Minimum { get; set; }
    public double Maximum { get; set; }
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        double number;
        if (!double.TryParse(value.ToString(), out number))
        {
            return new ValidationResult(false, "Invalid number format");
        }
        if (number > Maximum || number < Minimum)
        {
            if(!string.IsNullOrEmpty(ErrorMessage))
            {
                return new ValidationResult(false, ErrorMessage);
            }
            else
            {
                return new ValidationResult(false, string.Format("Value should between {0} and {1}", Minimum, Maximum));
            }
           
        }
        return ValidationResult.ValidResult;
    }
}

完美主义者

经过改进后的方案可以说是相当完美了,但是还是发现几个奇怪的现象:
1、TextBox代码比较臃肿,每个TextBox至少需要9行代码,而且还无法使用模板解决
2、属性的范围及错误提示都在xaml中
3、Submit时,是对Texbox进行验证,而非属性本身

针对第一点了其实还能接受,至于第二点,如果数据的验证范规则或者范围改变,需要修改前端代码,更多人倾向于在后端写验证规则,前端调用。所以有没有一种方式是后端验证,将验证的结果通知到UI呢?这个就是我们下一篇文章要介绍的。《WPF的TextBox输入验证之IDataErrorInfo验证》。

源码下载

立即下载
标签: 暂无
最后更新:2020-09-27

王彦为

新生代农民工,十年医疗器械行业从业经验,现居苏州。爱生活,爱做梦。

打赏 点赞
< 上一篇
下一篇 >

文章评论

  • Thomasnibly

    Подъемный стол гидравлический двухножничный. Арт. Артикул 67-5007. Высота подъёма: 280-900 мм. Поднятие на большую высоту. Используются в качестве подъемных лифтов для людей и грузов. Перегрузочные https://energo-pole.ru/skladskaya-tekhnika/podemnye-stoly/peredvizhnye-podemnye-stoly/ столы. Грузоподъемность: 500 кг. Высота подъема: 880 мм. Размер платформы: 850х500 мм. Колеса: 125х40 мм. Гарантия: 12 мес.

    2025-08-23
    回复
  • Danielavani

    Economical vacation nearby toward house Mild beaches calm brine with brine Affordable costs Entire such would craft individual strand getaway lasting Secure own pass toward oasis right now

    2025-08-23
    回复
  • Thomasnibly

    Высота подъёма: 280-900 мм. Грузоподъемность: 2000 кг. Еще -5 В качестве защиты от раздавливания подъемный стол оснащен кромкой безопасности расположенной под наружными краями платформы. При активации она прекращает опускание. Для продолжения опускания платформа должна быть поднята для сброса защиты. Грузоподъемность от 2000 до 4000 кг Высота подъема от 1600 до 1700 мм. Высота подъёма: 450-1500 мм.

    2025-08-19
    回复
  • Danielavani

    Full Throttle Summer Savings Event Down are heating discounts - on tools and from DJI GEPRC RadioMaster Ethix TBS Lumenier Flywoo EMAX and around now before GetFPV’s Full Throttle Summer Savings event is on

    2025-08-19
    回复
  • Danielavani

    Were prepared to save the day — a qualified team prepared to fix your plumbing disaster and reinstate function in your property Our fast action works to - decrease the chance for high-cost serious corrections eventually. Discover our prompt and excellent service - immediately

    2025-08-19
    回复
  • ozdow

    <b><a href=https://momspace.ru/posle-rodov/>после родом</a></b>

    Может быть полезным: https://momspace.ru/articles/kak-izbavitsya-ot-izzhogi-pri-beremennosti-bezopasno-i-effektivno/ или <a href=https://momspace.ru/fertilnost/>фертильность это простыми словами</a>

    <b><a href=https://momspace.ru/rozhdeniye-rebenka/>свидетельство о рождении ребенка</a></b>

    2025-08-15
    回复
  • 取消回复

    COPYRIGHT © 2022 王彦为. ALL RIGHTS RESERVED.

    苏ICP备16063331号-1

    苏公网安备32050702011313号