C# 自定义文本框中的MaxLength属性中断

C# 自定义文本框中的MaxLength属性中断,c#,.net,wpf,inheritance,custom-controls,C#,.net,Wpf,Inheritance,Custom Controls,对于我的WPF应用程序,我基于文本框创建了两个自定义控件。其中包括NumericTextBox、WatermarkTextBox和ReturnTextBox 数字和水印继承自ReturnTextBox,后者继承自TextBox 当我去使用我的任何自定义文本框时,它们工作得非常好。唯一的问题似乎是NumericTextBox和MaxLength属性。该属性现在被忽略且不起作用。我的任何自定义控件中都没有重写或弄乱MaxLength属性的代码 当我在ReturnTextBox上使用MaxLength

对于我的WPF应用程序,我基于文本框创建了两个自定义控件。其中包括NumericTextBox、WatermarkTextBox和ReturnTextBox

数字和水印继承自ReturnTextBox,后者继承自TextBox

当我去使用我的任何自定义文本框时,它们工作得非常好。唯一的问题似乎是NumericTextBox和MaxLength属性。该属性现在被忽略且不起作用。我的任何自定义控件中都没有重写或弄乱MaxLength属性的代码

当我在ReturnTextBox上使用MaxLength时,它的工作原理与您预期的一样:

<ui:ReturnTextBox MaxLength="35" Width="500" Background="LightYellow" Text="{Binding BrRptCorpName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" TabIndex="2" />
数字文本框

public class NumericTextBox : ReturnTextBox
{
    #region Base Class Overrides

    static NumericTextBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericTextBox), new FrameworkPropertyMetadata(typeof(NumericTextBox)));
    }

    public static readonly DependencyProperty TypeProperty = DependencyProperty.Register("Type",
           typeof(NumericType), typeof(NumericTextBox), new UIPropertyMetadata (NumericType.Integer));
    public static readonly DependencyProperty SelectAllOnGotFocusProperty = DependencyProperty.Register("SelectAllOnGotFocus", 
           typeof(bool), typeof(NumericTextBox), new PropertyMetadata(false));

    [Description("Numeric Type of the TextBox"), Category("Common Properties")]
    public NumericType Type
    {
        get { return (NumericType)GetValue(TypeProperty); }
        set { SetValue(TypeProperty, value); }
    }

    [Description("Select text on focus"), Category("Common Properties")]
    public bool SelectAllOnGotFocus
    {
        get
        {
            return (bool)GetValue(SelectAllOnGotFocusProperty);
        }
        set
        {
            SetValue(SelectAllOnGotFocusProperty, value);
        }
    }

    protected override void OnPreviewTextInput(TextCompositionEventArgs e)
    {
        Text = ValidateValue(Type, Text);
        bool isValid = IsSymbolValid(Type, e.Text);
        e.Handled = !isValid;
        if (isValid)
        {
            int caret = CaretIndex;
            string text = Text;
            bool textInserted = false;
            int selectionLength = 0;

            if (SelectionLength > 0)
            {
                text = text.Substring(0, SelectionStart) + text.Substring(SelectionStart + SelectionLength);
                caret = SelectionStart;
            }
            if (e.Text == NumberFormatInfo.CurrentInfo.NumberDecimalSeparator)
            {
                while (true)
                {
                    int ind = text.IndexOf(NumberFormatInfo.CurrentInfo.NumberDecimalSeparator);
                    if (ind == -1)
                        break;
                    text = text.Substring(0, ind) + text.Substring(ind + 1);
                    if (caret > ind)
                        caret--;
                }
                if (caret == 0)
                {
                    text = "0" + text;
                    caret++;
                }
                else
                {
                    if (caret == 1 && string.Empty + text[0] == NumberFormatInfo.CurrentInfo.NegativeSign)
                    {
                        text = NumberFormatInfo.CurrentInfo.NegativeSign + "0" + text.Substring(1);
                        caret++;
                    }
                }

                if (caret == text.Length)
                {
                    selectionLength = 1;
                    textInserted = true;
                    text = text + NumberFormatInfo.CurrentInfo.NumberDecimalSeparator + "0";
                    caret++;
                }
            }
            else if (e.Text == NumberFormatInfo.CurrentInfo.NegativeSign)
            {
                textInserted = true;
                if (Text.Contains(NumberFormatInfo.CurrentInfo.NegativeSign))
                {
                    text = text.Replace(NumberFormatInfo.CurrentInfo.NegativeSign, string.Empty);
                    if (caret != 0)
                        caret--;
                }
                else
                {
                    text = NumberFormatInfo.CurrentInfo.NegativeSign + Text;
                    caret++;
                }
            }

            if (!textInserted)
            {
                text = text.Substring(0, caret) + e.Text +
                    ((caret < Text.Length) ? text.Substring(caret) : string.Empty);

                caret++;
            }

            try
            {
                double val = Convert.ToDouble(text);
                double newVal = val;//ValidateLimits(GetMinimumValue(_this), GetMaximumValue(_this), val);
                if (val != newVal)
                {
                    text = newVal.ToString();
                }
                else if (val == 0)
                {
                    if (!text.Contains(NumberFormatInfo.CurrentInfo.NumberDecimalSeparator))
                        text = "0";
                }
            }
            catch
            {
                text = "0";
            }

            while (text.Length > 1 && text[0] == '0' && string.Empty + text[1] != NumberFormatInfo.CurrentInfo.NumberDecimalSeparator)
            {
                text = text.Substring(1);
                if (caret > 0)
                    caret--;
            }

            while (text.Length > 2 && string.Empty + text[0] == NumberFormatInfo.CurrentInfo.NegativeSign && text[1] == '0' && string.Empty + text[2] != NumberFormatInfo.CurrentInfo.NumberDecimalSeparator)
            {
                text = NumberFormatInfo.CurrentInfo.NegativeSign + text.Substring(2);
                if (caret > 1)
                    caret--;
            }

            if (caret > text.Length)
                caret = text.Length;

            Text = text;
            CaretIndex = caret;
            SelectionStart = caret;
            SelectionLength = selectionLength;
            e.Handled = true;
        }

        base.OnPreviewTextInput(e);
    }

    private static string ValidateValue(NumericType type, string value)
    {
        if (string.IsNullOrEmpty(value))
            return string.Empty;

        value = value.Trim();
        switch (type)
        {
            case NumericType.Integer:
                try
                {
                    Convert.ToInt64(value);
                    return value;
                }
                catch
                {
                }
                return string.Empty;

            case NumericType.Decimal:
                try
                {
                    Convert.ToDouble(value);
                    return value;
                }
                catch
                {
                }
                return string.Empty;
        }

        return value;
    }

    private static bool IsSymbolValid(NumericType type, string str)
    {
        switch (type)
        {
            case NumericType.Decimal:
                if (str == NumberFormatInfo.CurrentInfo.NegativeSign ||
                    str == NumberFormatInfo.CurrentInfo.NumberDecimalSeparator)
                    return true;
                break;

            case NumericType.Integer:
                if (str == NumberFormatInfo.CurrentInfo.NegativeSign)
                    return true;
                break;

            case NumericType.Any:
                return true;
        }

        if (type.Equals(NumericType.Integer) || type.Equals(NumericType.Decimal))
        {
            foreach (char ch in str)
            {
                if (!Char.IsDigit(ch))
                    return false;
            }

            return true;
        }

        return false;
    }

    protected override void OnGotFocus(RoutedEventArgs e)
    {
        base.OnGotFocus(e);

        if (SelectAllOnGotFocus)
            SelectAll();
    }

    protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
    {
        if (!IsKeyboardFocused && SelectAllOnGotFocus)
        {
            e.Handled = true;
            Focus();
        }

        base.OnPreviewMouseLeftButtonDown(e);
    }
公共类NumericTextBox:ReturnTextBox
{
#区域基类重写
静态NumericTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericTextBox),new FrameworkPropertyMetadata(typeof(NumericTextBox));
}
公共静态只读DependencyProperty类型属性=DependencyProperty.Register(“类型”,
typeof(NumericType)、typeof(NumericTextBox)、新UIPropertyMetadata(NumericType.Integer));
公共静态只读DependencyProperty SelectAllOnGotFocusProperty=DependencyProperty.Register(“SelectAllOnGotFocus”,
typeof(bool)、typeof(NumericTextBox)、newpropertyMetadata(false));
[说明(“文本框的数字类型”)、类别(“通用属性”)]
公共数字类型
{
获取{return(NumericType)GetValue(TypeProperty);}
set{SetValue(TypeProperty,value);}
}
[说明(“焦点上选择文本”)、类别(“通用属性”)]
公共bool SelectAllOnGotFocus
{
得到
{
返回(bool)GetValue(选择AllongotFocusProperty);
}
设置
{
设置值(选择AllongotFocusProperty,值);
}
}
PreviewTestInput上的受保护覆盖无效(TextCompositionEventArgs e)
{
Text=ValidateValue(类型,Text);
bool isValid=IsSymbolValid(类型,e.Text);
e、 Handled=!isValid;
如果(有效)
{
int插入符号=插入索引;
字符串文本=文本;
bool textInserted=false;
int-selectionLength=0;
如果(选择长度>0)
{
text=text.Substring(0,SelectionStart)+text.Substring(SelectionStart+SelectionLength);
插入符号=选择开始;
}
if(e.Text==NumberFormatInfo.CurrentInfo.NumberDecimalSeparator)
{
while(true)
{
int ind=text.IndexOf(NumberFormatInfo.CurrentInfo.NumberDecimalSeparator);
如果(ind==-1)
打破
text=text.Substring(0,ind)+text.Substring(ind+1);
如果(插入符号>索引)
插入符号--;
}
如果(插入符号==0)
{
text=“0”+文本;
插入符号++;
}
其他的
{
if(插入符号==1&&string.Empty+文本[0]==NumberFormatInfo.CurrentInfo.NegativeSign)
{
text=NumberFormatInfo.CurrentInfo.NegativeSign+“0”+text.Substring(1);
插入符号++;
}
}
if(插入符号==text.Length)
{
selectionLength=1;
textInserted=true;
text=text+NumberFormatInfo.CurrentInfo.NumberDecimalSeparator+0;
插入符号++;
}
}
else if(e.Text==NumberFormatInfo.CurrentInfo.NegativeDesign)
{
textInserted=true;
if(Text.Contains(NumberFormatInfo.CurrentInfo.NegativeSign))
{
text=text.Replace(NumberFormatInfo.CurrentInfo.NegativeSign,string.Empty);
如果(插入符号!=0)
插入符号--;
}
其他的
{
text=NumberFormatInfo.CurrentInfo.NegativeSign+文本;
插入符号++;
}
}
如果(!textInserted)
{
text=text.Substring(0,插入符号)+e.text+
((插入符号1&&text[0]=“0”&&string.Empty+text[1]!=NumberFormatInfo.CurrentInfo.NumberDecimalSeparator)
{
text=text.子字符串(1);
如果(插入符号>0)
插入符号--;
}
而(text.Length>2&&string.Empty+text[0]==NumberFormatInfo.CurrentInfo.NegativeSign&&text[1]='0'&&string.Empty+text[2]!=NumberFormatInfo.CurrentInfo.NumberDecimalSeparator)
{
text=NumberFormatInfo.CurrentInfo.NegativeSign+text.Substring(2);
如果(插入符号>1)
插入符号--;
}
如果(插入符号>文本长度)
插入符号=文本长度;
文本=文本;
CaretIndex=插入符号;
选择开始=插入符号;
SelectionLength=SelectionLength;
e、 已处理=正确;
public class ReturnTextBox : TextBox
{
    static ReturnTextBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ReturnTextBox), new FrameworkPropertyMetadata(typeof(ReturnTextBox)));
    }

    protected override void OnPreviewKeyDown(KeyEventArgs e)
    {
        if (e.Key == Key.Return)
        {
            e.Handled = true;
            MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
        }
        base.OnPreviewKeyDown(e);
    }
}
public class NumericTextBox : ReturnTextBox
{
    #region Base Class Overrides

    static NumericTextBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericTextBox), new FrameworkPropertyMetadata(typeof(NumericTextBox)));
    }

    public static readonly DependencyProperty TypeProperty = DependencyProperty.Register("Type",
           typeof(NumericType), typeof(NumericTextBox), new UIPropertyMetadata (NumericType.Integer));
    public static readonly DependencyProperty SelectAllOnGotFocusProperty = DependencyProperty.Register("SelectAllOnGotFocus", 
           typeof(bool), typeof(NumericTextBox), new PropertyMetadata(false));

    [Description("Numeric Type of the TextBox"), Category("Common Properties")]
    public NumericType Type
    {
        get { return (NumericType)GetValue(TypeProperty); }
        set { SetValue(TypeProperty, value); }
    }

    [Description("Select text on focus"), Category("Common Properties")]
    public bool SelectAllOnGotFocus
    {
        get
        {
            return (bool)GetValue(SelectAllOnGotFocusProperty);
        }
        set
        {
            SetValue(SelectAllOnGotFocusProperty, value);
        }
    }

    protected override void OnPreviewTextInput(TextCompositionEventArgs e)
    {
        Text = ValidateValue(Type, Text);
        bool isValid = IsSymbolValid(Type, e.Text);
        e.Handled = !isValid;
        if (isValid)
        {
            int caret = CaretIndex;
            string text = Text;
            bool textInserted = false;
            int selectionLength = 0;

            if (SelectionLength > 0)
            {
                text = text.Substring(0, SelectionStart) + text.Substring(SelectionStart + SelectionLength);
                caret = SelectionStart;
            }
            if (e.Text == NumberFormatInfo.CurrentInfo.NumberDecimalSeparator)
            {
                while (true)
                {
                    int ind = text.IndexOf(NumberFormatInfo.CurrentInfo.NumberDecimalSeparator);
                    if (ind == -1)
                        break;
                    text = text.Substring(0, ind) + text.Substring(ind + 1);
                    if (caret > ind)
                        caret--;
                }
                if (caret == 0)
                {
                    text = "0" + text;
                    caret++;
                }
                else
                {
                    if (caret == 1 && string.Empty + text[0] == NumberFormatInfo.CurrentInfo.NegativeSign)
                    {
                        text = NumberFormatInfo.CurrentInfo.NegativeSign + "0" + text.Substring(1);
                        caret++;
                    }
                }

                if (caret == text.Length)
                {
                    selectionLength = 1;
                    textInserted = true;
                    text = text + NumberFormatInfo.CurrentInfo.NumberDecimalSeparator + "0";
                    caret++;
                }
            }
            else if (e.Text == NumberFormatInfo.CurrentInfo.NegativeSign)
            {
                textInserted = true;
                if (Text.Contains(NumberFormatInfo.CurrentInfo.NegativeSign))
                {
                    text = text.Replace(NumberFormatInfo.CurrentInfo.NegativeSign, string.Empty);
                    if (caret != 0)
                        caret--;
                }
                else
                {
                    text = NumberFormatInfo.CurrentInfo.NegativeSign + Text;
                    caret++;
                }
            }

            if (!textInserted)
            {
                text = text.Substring(0, caret) + e.Text +
                    ((caret < Text.Length) ? text.Substring(caret) : string.Empty);

                caret++;
            }

            try
            {
                double val = Convert.ToDouble(text);
                double newVal = val;//ValidateLimits(GetMinimumValue(_this), GetMaximumValue(_this), val);
                if (val != newVal)
                {
                    text = newVal.ToString();
                }
                else if (val == 0)
                {
                    if (!text.Contains(NumberFormatInfo.CurrentInfo.NumberDecimalSeparator))
                        text = "0";
                }
            }
            catch
            {
                text = "0";
            }

            while (text.Length > 1 && text[0] == '0' && string.Empty + text[1] != NumberFormatInfo.CurrentInfo.NumberDecimalSeparator)
            {
                text = text.Substring(1);
                if (caret > 0)
                    caret--;
            }

            while (text.Length > 2 && string.Empty + text[0] == NumberFormatInfo.CurrentInfo.NegativeSign && text[1] == '0' && string.Empty + text[2] != NumberFormatInfo.CurrentInfo.NumberDecimalSeparator)
            {
                text = NumberFormatInfo.CurrentInfo.NegativeSign + text.Substring(2);
                if (caret > 1)
                    caret--;
            }

            if (caret > text.Length)
                caret = text.Length;

            Text = text;
            CaretIndex = caret;
            SelectionStart = caret;
            SelectionLength = selectionLength;
            e.Handled = true;
        }

        base.OnPreviewTextInput(e);
    }

    private static string ValidateValue(NumericType type, string value)
    {
        if (string.IsNullOrEmpty(value))
            return string.Empty;

        value = value.Trim();
        switch (type)
        {
            case NumericType.Integer:
                try
                {
                    Convert.ToInt64(value);
                    return value;
                }
                catch
                {
                }
                return string.Empty;

            case NumericType.Decimal:
                try
                {
                    Convert.ToDouble(value);
                    return value;
                }
                catch
                {
                }
                return string.Empty;
        }

        return value;
    }

    private static bool IsSymbolValid(NumericType type, string str)
    {
        switch (type)
        {
            case NumericType.Decimal:
                if (str == NumberFormatInfo.CurrentInfo.NegativeSign ||
                    str == NumberFormatInfo.CurrentInfo.NumberDecimalSeparator)
                    return true;
                break;

            case NumericType.Integer:
                if (str == NumberFormatInfo.CurrentInfo.NegativeSign)
                    return true;
                break;

            case NumericType.Any:
                return true;
        }

        if (type.Equals(NumericType.Integer) || type.Equals(NumericType.Decimal))
        {
            foreach (char ch in str)
            {
                if (!Char.IsDigit(ch))
                    return false;
            }

            return true;
        }

        return false;
    }

    protected override void OnGotFocus(RoutedEventArgs e)
    {
        base.OnGotFocus(e);

        if (SelectAllOnGotFocus)
            SelectAll();
    }

    protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
    {
        if (!IsKeyboardFocused && SelectAllOnGotFocus)
        {
            e.Handled = true;
            Focus();
        }

        base.OnPreviewMouseLeftButtonDown(e);
    }