简化 XAML 转换器中电话号码上的正则表达式



C# 正则表达式

下面是一个简单的 WPF 转换器,它使用正则表达式显示带有电话号码掩码的一致文本框:

public class MyStringToPhoneConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    if (value == null)
        return string.Format("(   )    -    ");
    //remove formating...returns a string of digits.
    string phoneNo = value.ToString().Replace("(", string.Empty).Replace(")", string.Empty).Replace(" ", string.Empty).Replace("-", string.Empty);
    // All displayed formating in WPF depends on the control FontSytle. Use a fixed-width,  monospaced, font with no kerning.
    // Examples: Consolas, Courier New, Lucida Console, MS Gothic
    switch (phoneNo.Length)
    {
        case 0:
            return string.Format("(   )    -   ");
        case 1:
            return Regex.Replace(phoneNo, @"(d{1})", "($1  )    -    ");
        case 2:
            return Regex.Replace(phoneNo, @"(d{2})", "($1 )    -    ");
        case 3:
            return Regex.Replace(phoneNo, @"(d{3})", "($1)    -    ");
        case 4:
            return Regex.Replace(phoneNo, @"(d{3})(d{1})", "($1) $2  -    ");
        case 5:
            return Regex.Replace(phoneNo, @"(d{3})(d{2})", "($1) $2 -    ");
        case 6:
            return Regex.Replace(phoneNo, @"(d{3})(d{3})", "($1) $2-    ");
        case 7:
            return Regex.Replace(phoneNo, @"(d{3})(d{3})(d{1})", "($1) $2-$3   ");
        case 8:
            return Regex.Replace(phoneNo, @"(d{3})(d{3})(d{2})", "($1) $2-$3  ");
        case 9:
            return Regex.Replace(phoneNo, @"(d{3})(d{3})(d{3})", "($1) $2-$3 ");
        case 10:
            return Regex.Replace(phoneNo, @"(d{3})(d{3})(d{4})", "($1) $2-$3");
        case 11:
            return Regex.Replace(phoneNo, @"(d{1})(d{3})(d{3})(d{4})", "$1-$2-$3-$4");
        default:
            return phoneNo;
    }
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
    return value;
}

}

这似乎非常重复,必须为每个字符串长度编写不同的字符串和正则表达式。

是否有一个或两个正则表达式可以处理具有一致输出格式的不同字符串长度?(我真的不关心 11 位数字:)(

蒂亚

下面是摆脱

多个正则表达式模板和替换字符串的尝试。我想出的正则表达式有点复杂,更换过程需要一个自定义评估器。无论如何,它似乎达到了预期的目标。

一些评论:

  • (?<!d.*) - 确保匹配项以第 1 位数字开头
  • ((?=d{11})d{1})? - 提供所有 11 位数字时匹配第一组(1 位数字(
  • (d{1,3}) - 允许部分填充的组
  • |^(?!.*d) - 未找到数字时仍然匹配
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    //remove formating...returns a string of digits.
    string phoneNo = Regex.Replace(value?.ToString() ?? string.Empty, @"[()- ]", string.Empty);
    return Regex.Replace(phoneNo, @"(?<!d.*)((?=d{11})d{1})?(d{1,3})(d{1,3})?(d{1,4})?|^(?!.*d)", m =>
    {
        var gr1 = m.Groups[1].Value;
        var gr2 = m.Groups[2].Value.PadRight(3);
        var gr3 = m.Groups[3].Value.PadRight(3);
        var gr4 = m.Groups[4].Value.PadRight(4);
        return m.Groups[1].Success
            ? $"{gr1}-{gr2}-{gr3}-{gr4}"
            : $"({gr2}) {gr3}-{gr4}";
    });
}

最新更新