Regex正则表达式扩展

using System.Text.RegularExpressions;

正则表达式认可的特殊字符有:
. * [ ] ^ $ { } + ? | ( )

^ $的意思是对应的表示从这里开始^到$部分结束;

(?:pattern) 表示将pattern部分组合成一个可统一操作的组合项;

?重复是一个次或者0次

常用判断

IsMatch

/// <summary>
/// 验证字符串是否匹配正则表达式规则
/// </summary>
/// <param name="txt">待验证字符串</param>
/// <param name="pattern">正则表达式字符串</param>
/// <param name="bIgnoreCase">匹配时是否不区分大小写(默认不区分大小写)</param>
/// <param name="bValidateWhiteSpace">是否验证空白字符串(默认不验证)</param>
/// <returns></returns>
bool IsMatch(string txt, string pattern, bool bIgnoreCase = false, bool bValidateWhiteSpace = false)
{
    // 不验证空白字符串而待验证字符串为空白字符串,则不匹配  
    if (!bValidateWhiteSpace && string.IsNullOrWhiteSpace(txt))
    {
        return true;    // 放过
    }
    System.Text.RegularExpressions.Regex reg = null;
    if (bIgnoreCase)
    {
        reg = new Text.RegularExpressions.Regex(pattern, Text.RegularExpressions.RegexOptions.IgnoreCase);
    }
    else
    {
        reg = new Text.RegularExpressions.Regex(pattern);
    }
    return reg.IsMatch(txt);
}

IP

IP: (0-255).(0-255).(0-255).(0-255)

@"^(?: (?: (25[0-5])|(2[0-4]d)|((1d{2})|([1-9]?d))).){3}(?:(25[0-5])|(2[0-4]d)|((1d{2})|([1-9]?d)))$";
@"(?: (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9])";

字符 ^ 和 $ 同时使用时,表示精确匹配

URL

@"[w]+://[ ^ /s?#]+[ ^ s?#]+(?:?[ ^ s#])?(?:#[^s])?"

Email

@"[w.+-]+@[w.-]+.[w.-]+"

文件路径

@" ^ ([a-zA-Z]:)?[^/: *?""<>|,]*$"

文件路径中不允许的特殊字符

@" ^ [^/: *?""<>|,]+$"
System.IO.Path.GetInvalidPathChars()

Point / GPS

@"^-?[0-9].?[0-9]+,-?[0-9].?[0-9]+$"

非零的正整数

@"^ [1-9]d*$"

非负数

@"^d*$"

纯中文

@"^ [u4e00-u9fa5]*$"

空格

@"s+"
s匹配任意的空白符,包括空格,制表符(tab),换行符,中文全角空格。

空格和非法字符

~!¥……()——+《》?·,。、;‘【】$^()[]
@"([ ]+)|([~]+)|([!]+)|([¥]+)|([……]+)|([(]+)|([)]+)|([——]+)|([+]+)|([《]+)|([》]+)|([?]+)|([·]+)|([,]+)|([。]+)|([、]+)|([;]+)|([‘]+)|([【]+)|([】]+)|([$]+)|([^]+)|([(]+)|([)]+)|([[]+)|([]]+)"

后端字符串验证

public partial class UserControl1 : UserControl, IUserControlValidate
{
    private void ButtonOk_Click(object sender, RoutedEventArgs e)
    {
        if (!CheckData())
        {
            return;
        }
        // TODO
    }
    
    public bool CheckData()
    {
        if (!this.IsValid())
        {
            Console.WriteLine("数据错误!");
            return false;
        }
        if (!PageValidate.VerifyStringFormat(str, "IP地址", Regex_IP, Regext_Ip_Tip))
        {
            Console.WriteLine(PageValidate.ErrorMessage);
            return false;
        }
        // ......
        return true;
    }
}
public static class PageValidate
{
    /// <summary>
    /// 错误提示
    /// </summary>
    public static string ErrorMessage { get; set; }

    #region 公有
    /// <summary>
    /// 验证是否符合标准字符串,True符合
    /// </summary>
    /// <param name="inputTxt">待验证字符串</param>
    /// <param name="tipName">验证目标的提示名称</param>
    /// <param name="pattern">正则表达式字符串</param>
    /// <param name="tipFormatMsg">正确格式的提示信息</param>
    /// <returns></returns>
    public static bool VerifyStringFormat(string inputTxt, string tipName, string pattern, string tipFormatMsg)
    {
        ErrorMessage = $"{tipName}不符合指定格式:{tipFormatMsg}!";
        return IsMatch(inputTxt, pattern);
    }
    /// <summary>
    /// 判空
    /// </summary>
    /// <param name="inputTxt">待验证字符串</param>
    /// <param name="tipName">验证目标的提示名称</param>
    /// <returns></returns>
    public static bool VerifyEmpty(string inputTxt, string tipName)
    {
        if (string.IsNullOrWhiteSpace(inputTxt))
        {
            ErrorMessage = tipName + "不能为空!";
            return true;
        }
        ErrorMessage = string.Empty;
        return false;
    }
    /// <summary>
    /// 整数
    /// </summary>
    /// <param name="inputTxt">待验证字符串</param>
    /// <param name="tipName">验证目标的提示名称</param>
    /// <returns></returns>
    public static bool VerifyInteger(string inputTxt, string tipName)
    {
        // 判断效率快于正则
        if (string.IsNullOrEmpty(inputTxt) || int.TryParse(inputTxt, out _))
        {
            ErrorMessage = string.Empty;
            return true;
        }
        ErrorMessage = tipName + "必须是整数!";
        return false;
    }
    /// <summary>
    /// 非零的正整数
    /// </summary>
    /// <param name="inputTxt">待验证字符串</param>
    /// <param name="tipName">验证目标的提示名称</param>
    /// <returns></returns>
    public static bool VerifyPositiveInteger(string inputTxt, string tipName)
    {
        if (string.IsNullOrEmpty(inputTxt) || (int.TryParse(inputTxt, out int result) && result > 0))
        {
            ErrorMessage = string.Empty;
            return true;
        }
        ErrorMessage = tipName + "必须是非零的正整数!";
        return false;
    }
    /// <summary>
    /// 非负整数(0和正整数)
    /// </summary>
    /// <param name="inputTxt">待验证字符串</param>
    /// <param name="tipName">验证目标的提示名称</param>
    /// <returns></returns>
    public static bool VerifyNonnegativeInteger(string inputTxt, string tipName)
    {
        if (string.IsNullOrEmpty(inputTxt) || (int.TryParse(inputTxt, out int result) && result >= 0))
        {
            ErrorMessage = string.Empty;
            return true;
        }
        ErrorMessage = tipName + "必须是非负整数!";
        return false;
    }
    /// <summary>
    /// 浮点数
    /// </summary>
    /// <param name="inputTxt">待验证字符串</param>
    /// <param name="tipName">验证目标的提示名称</param>
    /// <returns></returns>
    public static bool VerifyFloat(string inputTxt, string tipName)
    {
        if (string.IsNullOrEmpty(inputTxt) || float.TryParse(inputTxt, out _))
        {
            ErrorMessage = string.Empty;
            return true;
        }
        ErrorMessage = tipName + "必须是浮点数!";
        return false;
    }

    #endregion

    /// <summary>
    /// 验证字符串是否匹配正则表达式规则
    /// </summary>
    /// <param name="txt">待验证字符串</param>
    /// <param name="pattern">正则表达式字符串</param>
    /// <param name="bIgnoreCase">匹配时是否不区分大小写(默认不区分大小写)</param>
    /// <param name="bValidateWhiteSpace">是否验证空白字符串(默认不验证)</param>
    /// <returns></returns>
    private static bool IsMatch(string txt, string pattern, bool bIgnoreCase = false, bool bValidateWhiteSpace = false)
    {
        // 不验证空白字符串而待验证字符串为空白字符串,则不匹配  
        if (!bValidateWhiteSpace && string.IsNullOrWhiteSpace(txt))
        {
            return true;    // 放过
        }
        System.Text.RegularExpressions.Regex reg = null;
        if (bIgnoreCase)
        {
            reg = new System.Text.RegularExpressions.Regex(pattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
        }
        else
        {
            reg = new System.Text.RegularExpressions.Regex(pattern);
        }
        return reg.IsMatch(txt);
    }
}
/// <summary>
/// 页面验证接口
/// </summary>
public interface IUserControlValidate
{
    /// <summary>
    /// 检验相关数据合法性
    /// </summary>
    /// <returns></returns>
    bool CheckData();
}

前端特殊类型验证

比如TextBox的Text是字符串形式,如果绑定其他类型(int等),在输入特殊字符串时会因为转换失败,相应属性还会保留以前的正确值,而TextBox展示与属性不一致。

当输入是空字符串时,后台属性是合法的int值,且提示不友好。
此时后端验证就太晚了,且错误转换的属性无法通过绑定对象进行验证(压根没有转换,还是合法值,只会略过后端验证),需要进行前端验证。

xmlns:util="clr-namespace:XXX.Utility"

<TextBox>
    <TextBox.Text>
        <Binding Path="PropertyName1">
            <Binding.ValidationRules>
                <util:NotNullValidationRule/>
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>
using System.Globalization;
using System.Windows.Controls;

/// <summary>
/// 不能为空验证
/// </summary>
internal class NotNullValidationRule : ValidationRule
{
    public NotNullValidationRule()
    {
        ValidatesOnTargetUpdated = true;
    }
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        if (value is string val)
        {
            if (string.IsNullOrWhiteSpace(val))
            {
                return new ValidationResult(false, "不能为空!");
            }
        }
        return ValidationResult.ValidResult;
    }
}
using System.Windows;
using System.Windows.Controls;
/// <summary>
/// 验证依赖对象绑定的数据是否合法
/// true合法,false不合法
/// </summary>
/// <param name="instance"></param>
/// <returns></returns>
public static bool IsValid(this DependencyObject instance)
{
    return !Validation.GetHasError(instance) &&
        LogicalTreeHelper.GetChildren(instance).OfType<DependencyObject>().All(child => child.IsValid());
}

数据类型对象验证

XAML

<TextBox Text="{Binding IntegerPara, ValidatesOnDataErrors=True, NotifyOnValidationError=True, ValidatesOnExceptions=True}">
    <TextBox.Style>
        <Style TargetType="TextBox">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="True">
                    <Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)/ErrorContent}"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    <TextBox.Style>
<TextBox>

数据类型

public partial class DemoEntity : ValidEntityBase
{
    private int _integerPara;
    /// <summary>
    /// 具体整数参数1
    /// </summary>
    public int IntegerPara
    {
        get => _integerPara;
        set => UpdateProperty(ref _integerPara, value);
    }

    private string _stringPara;
    /// <summary>
    /// 具体字符串参数2
    /// </summary>
    public string StringPara
    {
        get => _stringPara;
        set => UpdateProperty(ref _stringPara, value);
    }

    /// <summary>
    /// 待验证的属性关联的元数据类
    /// </summary>
    private class DemoEntity_Metadata
    {
        [Display(Name = "具体整数参数1")]
        [Required(ErrorMessage = "{0} 不能为空!")]
        [Range(10, 65535, ErrorMessage = "{0} 必须在10-65525之间!")]
        public int IntegerPara { get; set; }

        [Display(Name = "具体字符串参数2")]
        [Required(ErrorMessage = "{0} 不能为空!")]
        [StringLength(255, ErrorMessage = "{0} 输入字符串过长!")]
        [RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}", ErrorMessage = "{0} 指定格式不正确!!!")]
        [CustomValidation(typeof(CustomValidataionUtils), "CustomValidate1")]
        public string StringPara { get; set; }

    }
    public override string this[string columnName] => ValidateProperty<DemoEntity_Metadata>(this, columnName);
}

验证基类

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

/// <summary>
/// 待验证实体基类
/// </summary>
public partial class ValidEntityBase : NotifyPropertyChangedEx, IDataErrorInfo
{
    public virtual string this[string columnName] => string.Empty;
    public string Error => null;
    /// <summary>
    /// 验证属性
    /// </summary>
    /// <typeparam name="MetadataType"></typeparam>
    /// <param name="obj">属性所属对象</param>
    /// <param name="propertyName">属性名称</param>
    /// <returns></returns>
    internal string ValidateProperty<MetadataType>(object obj, string propertyName)
    {
        if (string.IsNullOrEmpty(propertyName))
        {
            return string.Empty;
        }
        Type targetType = obj.GetType();
        if (targetType != typeof(MetadataType))
        {
            TypeDescriptor.AddProviderTransparent(new AssociatedMetadataTypeTypeDescriptionProvider(targetType, typeof(MetadataType)), targetType);
        }
        object propertyValue = targetType.GetProperty(propertyName).GetValue(obj, null);
        ValidationContext validationContext = new ValidationContext(obj, null, null)
        {
            MemberName = propertyName
        };
        List<ValidationResult> validationResults = new List<ValidationResult>();
        _ = Validator.TryValidateProperty(propertyValue, validationContext, validationResults);
        return validationResults.Count > 0 ? validationResults.First().ErrorMessage : string.Empty;
    }
}

验证

private void Button_Click(object sender, RoutedEventArgs e)
{
    if (!this.IsValid())
    {
        var btn = (Button)sender;
        btn.CommandParameter = false;
        MessageBox.Show("ERROR!");
        // MVVM 可在ViewModel里提示验证错误信息
    }
}

其他复杂验证集合

public class CustomValidataionUtils
{
    public static ValidationResult CustomValidate1(string value)
    {
        // TODO
        return ValidationResult.Success;
    }

}
原文地址:https://www.cnblogs.com/wesson2019-blog/p/12127219.html