备份一段代码,用于提前测试textbox输入字符后的字符串

时间:2021-07-15
本文章向大家介绍备份一段代码,用于提前测试textbox输入字符后的字符串,主要包括备份一段代码,用于提前测试textbox输入字符后的字符串使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace XYY.Windows.SAAS.WpfExtention.AttachedProperties
{
    public class InputAttachedProperties
    {
        #region 附加属性
        public static bool GetEnableInputValidate(DependencyObject obj)
        {
            return (bool)obj.GetValue(EnableInputValidateProperty);
        }
        public static void SetEnableInputValidate(DependencyObject obj, bool value)
        {
            obj.SetValue(EnableInputValidateProperty, value);
        }
        //是否使用输入校验
        public static readonly DependencyProperty EnableInputValidateProperty =
            DependencyProperty.RegisterAttached("EnableInputValidate", typeof(bool), typeof(InputAttachedProperties), new PropertyMetadata(false, (a, b) =>
            {
                if (a is TextBox tb && b.NewValue is bool en)
                {
                    if (en)
                    {
                        tb.PreviewTextInput += Tb_PreviewTextInput;
                        tb.GotFocus += Tb_GotFocus;
                        tb.TextChanged += Tb_TextChanged;
                        tb.AcceptsReturn = false;
                        tb.AcceptsTab = false;
                        tb.PreviewDrop += Tb_PreviewDrop;
                        CommandManager.AddPreviewExecutedHandler(tb, tbPreviewCommandExcute);
                        //禁用输入法
                        if (tb.IsInputMethodEnabled)
                        {
                            InputMethod.SetIsInputMethodEnabled(tb, false);
                            InputMethod.Current.ImeState = InputMethodState.Off;
                        }
                    }
                    else
                    {
                        tb.PreviewTextInput -= Tb_PreviewTextInput;
                        tb.GotFocus -= Tb_GotFocus;
                        tb.AcceptsReturn = true;
                        tb.AcceptsTab = true;
                        tb.PreviewDrop -= Tb_PreviewDrop;
                        CommandManager.RemovePreviewExecutedHandler(tb, tbPreviewCommandExcute);
                        //禁用输入法
                        if (tb.IsInputMethodEnabled)
                        {
                            InputMethod.SetIsInputMethodEnabled(tb, true);
                            InputMethod.Current.ImeState = InputMethodState.DoNotCare;
                        }
                    }

                }
            }));

        private static void Tb_GotFocus(object sender, RoutedEventArgs e)
        {
            var tb = sender as TextBox;
            tb.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.ApplicationIdle, new Action(() =>
            {
                tb.SelectAll();
            }));
        }

        public static bool GetIsNumber(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsNumberProperty);
        }
        public static void SetIsNumber(DependencyObject obj, bool value)
        {
            obj.SetValue(IsNumberProperty, value);
        }
        //是否是数字 (不能有负号,小数)
        public static readonly DependencyProperty IsNumberProperty =
            DependencyProperty.RegisterAttached("IsNumber", typeof(bool), typeof(InputAttachedProperties), new PropertyMetadata(false));


        public static bool GetIsAmount(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsAmountProperty);
        }
        public static void SetIsAmount(DependencyObject obj, bool value)
        {
            obj.SetValue(IsAmountProperty, value);
        }
        //是否是金额 (可以有负号,小数)
        public static readonly DependencyProperty IsAmountProperty =
            DependencyProperty.RegisterAttached("IsAmount", typeof(bool), typeof(InputAttachedProperties), new PropertyMetadata(false));



        public static int GetDecimalPlace(DependencyObject obj)
        {
            return (int)obj.GetValue(DecimalPlaceProperty);
        }
        public static void SetDecimalPlace(DependencyObject obj, int value)
        {
            obj.SetValue(DecimalPlaceProperty, value);
        }
        //小数位数
        public static readonly DependencyProperty DecimalPlaceProperty =
            DependencyProperty.RegisterAttached("DecimalPlace", typeof(int), typeof(InputAttachedProperties), new PropertyMetadata(3));


        #endregion

        #region 校验方法
        private static void tbPreviewCommandExcute(object sender, ExecutedRoutedEventArgs e)
        {
            var tb = sender as TextBox;
            var isNumber = GetIsNumber(sender as TextBox);
            var isAmount = GetIsAmount(sender as TextBox);
            if (e.Command == ApplicationCommands.Cut ||
                e.Command == ApplicationCommands.Paste)
            {
                e.Handled = true;
            }
            if (e.Command is RoutedUICommand rc)
            {
                switch (rc.Name)
                {
                    case "MoveUpByLine":
                    case "MoveDownByLine":
                        e.Handled = true;
                        return;
                    case "Space":
                        if (isAmount || isNumber)
                            e.Handled = true;
                        return;
                    case "DeletePreviousWord":
                    case "DeleteNextWord":
                    case "Backspace":
                    case "Delete":
                        var result = TestFutureText(null, sender as TextBox, rc.Name);
                        //只有多个连续的0替换成只有一个
                        if (Regex.IsMatch(result, @"^-?00+$"))
                        {
                            tb.Text = Regex.Replace(result, @"0+", m => "0");
                            tb.CaretIndex = tb.Text.Length;
                            e.Handled = true;
                            return;
                        }
                        //小数删得只有末尾的.,把.也删了
                        if (Regex.IsMatch(result, @"\.0*$"))
                        {
                            tb.Text = Regex.Replace(result, @"\.0*$", m => string.Empty);
                            tb.CaretIndex = tb.Text.Length;

                            e.Handled = true;
                            return;
                        }
                        //整数部分删得只有-,把整数部分改为0
                        if (Regex.IsMatch(result, @"^-(?!\d)"))
                        {
                            tb.Text = result.Replace("-", "0");
                            tb.CaretIndex = 0;
                            tb.SelectionStart = 0;
                            tb.SelectionLength = 1;
                            e.Handled = true;
                            return;
                        }
                        //如果输入了.,但是没有整数部分,整数部分补0
                        if (Regex.IsMatch(result, @"^\."))
                        {
                            tb.Text = "0" + result;
                            tb.CaretIndex = 0;
                            tb.SelectionStart = 0;
                            tb.SelectionLength = 1;
                            e.Handled = true;
                            return;
                        }
                        //整数无意义的0去掉
                        //小数无意义的0去掉
                        if (Regex.IsMatch(result, @"(^.*\..*?)0+$"))
                        {
                            tb.Text = Regex.Match(result, @"(^.*\..*?)0+$").Groups[1].Value;
                            tb.CaretIndex = tb.Text.Length;
                            e.Handled = true;
                            return;
                        }

                        break;
                    default:
                        break;
                }
            }
        }

        private static void Tb_PreviewDrop(object sender, DragEventArgs e)
        {
            e.Handled = true;
            return;
        }

        private static void Tb_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
        {

            var previewText = e.Text;
            var tb = sender as TextBox;
            //禁用输入法
            if (tb.IsInputMethodEnabled)
            {
                InputMethod.SetIsInputMethodEnabled(tb, false);
                InputMethod.Current.ImeState = InputMethodState.Off;
            }
            var result = TestFutureText(previewText, tb);
            var isNumber = GetIsNumber(tb);
            var isAmount = GetIsAmount(tb);
            var decimalSpace = GetDecimalPlace(tb);
            //isAmoust和isNumber互斥,且优先级高于isNumber
            if (isAmount)
                isNumber = false;
            if (isNumber || isAmount)
            {
                //不能输入空格
                if (Regex.IsMatch(result, @"\s+"))
                {
                    e.Handled = true;
                    return;
                }
                //全0的时候 ,多个连接的0替换成只有一个
                if (Regex.IsMatch(result, @"^-?00+$"))
                {
                    tb.Text = Regex.Replace(result, @"0+", m => "0");
                    tb.CaretIndex = tb.Text.Length;
                    e.Handled = true;
                    return;
                }

            }
            //纯数字模式
            if (isNumber)
            {
                //如果不是纯数字,处理掉输入信号
                if (!Regex.IsMatch(result, @"^\d+$"))
                {
                    e.Handled = true;
                    return;
                }
                //如果只输了0再输其他的数字,直接替换掉0
                if (tb.Text == "0" && tb.SelectionLength == 0 && tb.CaretIndex == 1)
                {
                    tb.Text = previewText;
                    tb.CaretIndex = 1;
                    e.Handled = true;
                    return;
                }
                //不能输入没有意义的0
                if (Regex.IsMatch(result, @"^0(?=\d)"))
                {
                    e.Handled = true;
                    return;
                }
            }
            //金额模式(正负值 小数点)
            if (isAmount)
            {
                //只能输入数字和小数点和负号
                if (!Regex.IsMatch(previewText, @"[\d\.\-]"))
                {
                    e.Handled = true;
                    return;
                }
                //如果光标右边是. 什么都不做,光标右移一位
                if (Regex.IsMatch(tb.Text, @"\d+\.\d+") && previewText == "." && tb.Text.Length != tb.CaretIndex && tb.Text[tb.CaretIndex] == '.')
                {
                    tb.CaretIndex++;
                }
                //小数点如果超过限制,中断输入信号
                if (Regex.IsMatch(result, @"\.\d+$"))
                {
                    var len = Regex.Match(result, @"\.(\d+$)").Groups[1].Length;
                    if (len > decimalSpace)
                    {
                        e.Handled = true;
                        return;
                    }
                }
                //如果是-.的情况 改为-0.1
                if (result == "-.")
                {
                    tb.Text = "-0.1";
                    tb.CaretIndex = tb.Text.Length - 1;
                    tb.SelectionStart = tb.Text.Length - 1;
                    tb.SelectionLength = 1;
                    e.Handled = true;
                    return;
                }
                if (result == ".")
                {
                    tb.Text = "0.1";
                    tb.CaretIndex = tb.Text.Length - 1;
                    tb.SelectionStart = tb.Text.Length - 1;
                    tb.SelectionLength = 1;
                    e.Handled = true;
                    return;
                }


                //如果有多个小数点不让输入
                if (Regex.Matches(result, @"\.").Count > 1)
                {
                    e.Handled = true;
                    return;
                }
                //如果有多个负号不让输入
                if (Regex.Matches(result, @"\-").Count > 1)
                {
                    e.Handled = true;
                    return;
                }
                //如果负号不是在最前面不让输入
                if (Regex.IsMatch(result, @"(?<!^)\-"))
                {
                    e.Handled = true;
                    return;
                }
                //不能输入空格
                if (Regex.IsMatch(result, @"\s+"))
                {
                    e.Handled = true;
                    return;
                }
                //整数部分如果只输了0或-0,光标定位在0后面再输其他的数字,直接替换掉0
                if (((Regex.IsMatch(result, @"^0+") && tb.CaretIndex == 1) || (Regex.IsMatch(result, @"^-0+") && tb.CaretIndex == 2)) && tb.SelectionLength == 0)
                {
                    if (previewText != ".")
                    {
                        tb.Text = Regex.Replace(tb.Text, @"0+", m =>
                        {
                            if (m.Index == 0)
                            {
                                return previewText;
                            }
                            return m.Value;
                        });

                        tb.CaretIndex = tb.Text.IndexOf(previewText) + 1;
                        e.Handled = true;
                        return;
                    }
                }
                //小数点前面不能输入没有意义的0
                if (Regex.IsMatch(result, @"^-?0(?=\d)"))
                {
                    e.Handled = true;
                    return;
                }
                //小数点后面不能输没有意义的0,所以自动补1,1为选中状态
                if (Regex.IsMatch(result, @"\.\d*0$"))
                {
                    var decimalSpaceLen = Regex.Match(result, @"[^\.]+$").Value.Length;
                    if (decimalSpaceLen <= decimalSpace - 1)
                    {
                        tb.Text = result + "1";
                        tb.CaretIndex = tb.Text.Length - 1;
                        tb.SelectionStart = tb.CaretIndex;
                        tb.SelectionLength = 1;
                    }
                    e.Handled = true;
                    return;
                }
                //如果整数部分只输入了-号,自动补全为-1  1为选中状态
                if (Regex.IsMatch(result, @"^-(?!\d)"))
                {
                    tb.Text = result.Replace("-", "-1");
                    tb.CaretIndex = 1;
                    tb.SelectionStart = 1;
                    tb.SelectionLength = 1;
                    e.Handled = true;
                    return;
                }
                //如果在末尾输入了. ,自动补全为.1 ,1为选中状态
                if (Regex.IsMatch(result, @"\.$"))
                {
                    var i = result.IndexOf('.');
                    tb.Text = result.Replace(".", ".1");
                    tb.CaretIndex = i + 1;
                    tb.SelectionStart = i + 1;
                    tb.SelectionLength = 1;
                    e.Handled = true;
                    return;
                }

                //如果输入了.,但是没有整数部分,整数部分补0
                if (Regex.IsMatch(result, @"^\."))
                {
                    tb.Text = "0" + result;
                    tb.CaretIndex = 0;
                    tb.SelectionStart = 0;
                    tb.SelectionLength = 1;
                    e.Handled = true;
                    return;
                }


            }
        }

        private static string TestFutureText(string previewText, TextBox tb, string deleteMode = null)
        {
            var cindex = tb.CaretIndex;
            var sLen = tb.SelectionLength;
            var sStartIndex = tb.SelectionStart;
            var deleteStart = cindex >= sStartIndex ? sStartIndex : cindex;
            string futureText = string.Empty;
            //按删除的
            if (!string.IsNullOrEmpty(deleteMode))
            {
                //按删除键,且有选择字符时,直接删除选择的字符
                if (tb.SelectionLength > 0)
                {
                    switch (deleteMode)
                    {
                        case "DeletePreviousWord":
                        case "DeleteNextWord":
                        case "Backspace":
                        case "Delete":
                        default:
                            futureText = tb.Text.Remove(deleteStart, sLen);
                            break;
                    }
                }
                //按删除键,没有选择字符时
                else
                {
                    switch (deleteMode)
                    {
                        //ctrl+backspace 删除到 单词左边 
                        case "DeletePreviousWord":
                            if (cindex == 0)
                                return tb.Text;
                            var c = tb.Text[cindex - 1];
                            var isWord = Regex.IsMatch(c.ToString(), @"\w");
                            if (!isWord)
                            {
                                futureText = tb.Text.Remove(cindex - 1, 1);
                                return futureText;
                            }
                            var startindex = 0;
                            for (int i = 0; i < cindex; i++)
                            {
                                if (Regex.IsMatch(tb.Text[i].ToString(), @"\W"))
                                {
                                    startindex = i + 1;
                                }
                            }
                            futureText = tb.Text.Remove(startindex, cindex - startindex);
                            break;
                        //ctrl+delete 删除到 单词右边
                        case "DeleteNextWord":
                            if (cindex == tb.Text.Length)
                                return tb.Text;
                            var c2 = tb.Text[cindex];
                            var isWord2 = Regex.IsMatch(c2.ToString(), @"\w");
                            if (!isWord2)
                            {
                                futureText = tb.Text.Remove(cindex, 1);
                                return futureText;
                            }
                            var end = 0;
                            for (int i = cindex; i < tb.Text.Length; i++)
                            {
                                if (Regex.IsMatch(c2.ToString(), @"\w"))
                                    end = i;
                                else
                                    break;
                            }
                            futureText = tb.Text.Remove(cindex, end - cindex);

                            break;
                        //删除光标左边的字符1个或0个
                        case "Backspace":
                            futureText = tb.Text.Remove(deleteStart - 1 <= 0 ? 0 : deleteStart - 1, deleteStart >= 1 ? 1 : 0);
                            break;
                        //删除光标左右的字符1个或0个
                        case "Delete":
                            futureText = tb.Text.Remove(deleteStart, tb.Text.Length - deleteStart >= 1 ? 1 : 0);
                            break;
                        default:
                            break;
                    }
                }
            }
            //不是按删除的
            else
            {
                futureText = tb.Text.Remove(deleteStart, sLen).Insert(deleteStart, previewText);
            }
            Console.WriteLine(futureText);
            return futureText;
        }

        private static void Tb_TextChanged(object sender, TextChangedEventArgs e)
        {
            var tb = sender as TextBox;
            var isNumber = GetIsNumber(tb);
            var isAmount = GetIsAmount(tb);

            if ((isNumber || isAmount) && string.IsNullOrWhiteSpace(tb.Text))
            {
                tb.Text = "0";
                tb.SelectionStart = 0;
                tb.SelectionLength = 1;
            }
        }


        #endregion


    }
}

原文地址:https://www.cnblogs.com/nocanstillbb/p/15016485.html