【问题标题】:Silverlight numeric textbox?Silverlight 数字文本框?
【发布时间】:2009-12-29 21:58:52
【问题描述】:

我尝试创建自己的数字文本框,这是我的代码:

public class NumericTextBox : TextBox
{

    public NumericTextBox()
        : base()
    {
        this.Text = "0";
    }

    private void HandleKeyEvent(KeyEventArgs e)
    {
        e.Handled = true;
        if ((Keyboard.Modifiers & ModifierKeys.Alt) != 0)
        {
            return;
        }
        if (e.Key == Key.Back || e.Key == Key.Delete || e.Key == Key.Left || e.Key == Key.Right ||
            e.Key == Key.D0 || e.Key == Key.D1 || e.Key == Key.D2 || e.Key == Key.D3 || e.Key == Key.D4 || e.Key == Key.D5 || e.Key == Key.D6 ||
            e.Key == Key.D7 || e.Key == Key.D8 || e.Key == Key.D9 ||
            e.Key == Key.NumPad0 || e.Key == Key.NumPad1 || e.Key == Key.NumPad2 || e.Key == Key.NumPad3 || e.Key == Key.NumPad4 || e.Key == Key.NumPad5 || e.Key == Key.NumPad6 ||
            e.Key == Key.NumPad7 || e.Key == Key.NumPad8 || e.Key == Key.NumPad9)
        {
            e.Handled = false;
        }
        else if ((e.Key == Key.Subtract || (e.Key == Key.Unknown && e.PlatformKeyCode == 189)) && base.SelectionStart == 0 && (base.Text.Length == 0 || base.Text[0] != '-'))
        {
            e.Handled = false;
        }
    }

    protected override void OnKeyDown(KeyEventArgs e)
    {
        HandleKeyEvent(e);
        base.OnKeyDown(e);
    }

    protected override void OnKeyUp(KeyEventArgs e)
    {
        HandleKeyEvent(e);
        base.OnKeyUp(e);
    }
}

一切都像预期的那样工作,但是如果你按下 alt 和一些数字,它会创建与数字相对应的 ascii 符号。有没有办法阻止“alt + 数字组合? 似乎只是输入了 alt + 键而没有抛出 OnKeyUp 或 OnKeyDown ...

【问题讨论】:

    标签: c# silverlight


    【解决方案1】:

    我通过使用 TextChanged 事件让它工作,这是我的代码...

    public class NumericTextBox : TextBox
    {
    
        int value;
    
        public NumericTextBox()
            : base()
        {
            this.Text = "0";
            this.TextChanged += new TextChangedEventHandler(NumericTextBox_TextChanged);
        }
    
        void NumericTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            int selectionStart = base.SelectionStart;
            bool changed = false;
            List<char> charList = new List<char>();
            for (int i = 0; i < base.Text.Length; i++)
            {
                if (IsValidChar(base.Text[i], i))
                {
                    charList.Add(base.Text[i]);
                }
                else
                {
                    if (selectionStart >= i)
                    {
                        selectionStart--;
                    }
                    changed = true;
                }
            }
            if (changed)
            {
                string text = new string(charList.ToArray());
                this.Text = text;
                this.SelectionStart = selectionStart;
            }
            int newValue;
            if (!int.TryParse(this.Text, out newValue))
            {
                this.Text = value.ToString();
                this.SelectionStart = this.Text.Length;
            }
            else
            {
                value = newValue;
            }
        }
    
        private bool IsValidChar(char c, int index)
        {
            return ((c == '-' && index == 0) || c == '0' || c == '1' || c == '2' || c == '3' || c == '4' || c == '5' || c == '6' || c == '7' || c == '8' || c == '9');
        }
    
        private void HandleKeyEvent(KeyEventArgs e)
        {
            e.Handled = true;
            if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
            {
                e.Handled = false;
            }
            if (e.Key == Key.Back || e.Key == Key.Delete || e.Key == Key.Left || e.Key == Key.Right ||
                e.Key == Key.D0 || e.Key == Key.D1 || e.Key == Key.D2 || e.Key == Key.D3 || e.Key == Key.D4 || e.Key == Key.D5 || e.Key == Key.D6 ||
                e.Key == Key.D7 || e.Key == Key.D8 || e.Key == Key.D9 ||
                e.Key == Key.NumPad0 || e.Key == Key.NumPad1 || e.Key == Key.NumPad2 || e.Key == Key.NumPad3 || e.Key == Key.NumPad4 || e.Key == Key.NumPad5 || e.Key == Key.NumPad6 ||
                e.Key == Key.NumPad7 || e.Key == Key.NumPad8 || e.Key == Key.NumPad9)
            {
                e.Handled = false;
            }
            else if ((e.Key == Key.Subtract || (e.Key == Key.Unknown && e.PlatformKeyCode == 189)) && base.SelectionStart == 0 && (base.Text.Length == 0 || base.Text[0] != '-'))
            {
                e.Handled = false;
            }
        }
    
        protected override void OnKeyDown(KeyEventArgs e)
        {
            HandleKeyEvent(e);
            base.OnKeyDown(e);
        }
    
        protected override void OnKeyUp(KeyEventArgs e)
        {
            HandleKeyEvent(e);
            base.OnKeyUp(e);
        }
    }
    

    【讨论】:

    • 这是危险的,因为它假定一个数字是用“-”和“0”到“9”之间的数字写成的,这并非适用于所有文化。此外,您必须同时处理键和文本事件,所以这是最少工作的两倍 :) 我在下面发布了一个替代方案。
    【解决方案2】:

    这是一种替代方法,只需要附加属性和以下代码。 一、代码:

    public enum InputType
    {
        PositiveInteger,
        PositiveDecimal,
        PositiveNullableInteger,
        PositiveNullableDecimal,
    }
    
    public static class Input
    {
        public static readonly DependencyProperty TypeProperty =
            DependencyProperty.RegisterAttached("Type", typeof(InputType), typeof(TextBox),
                                                new PropertyMetadata(default(InputType), OnTypeChanged));
    
        public static void SetType(TextBox element, InputType value)
        {
            element.SetValue(TypeProperty, value);
        }
    
        public static InputType GetType(TextBox element)
        {
            return (InputType)element.GetValue(TypeProperty);
        }
    
        private class TextSelection
        {
            public string Text { get; private set; }
    
            public int SelectionStart { get; private set; }
    
            public int SelectionLength { get; private set; }
    
            public TextSelection(string text, int selectionStart, int selectionLength)
            {
                Text = text;
                SelectionStart = selectionStart;
                SelectionLength = selectionLength;
            }
        }
    
        private static readonly DependencyProperty PreviousTextSelectionProperty =
            DependencyProperty.RegisterAttached("PreviousTextSelection", typeof(TextSelection),
            typeof(TextBox), new PropertyMetadata(default(TextSelection)));
    
        private static void SetPreviousTextSelection(TextBox element, TextSelection value)
        {
            element.SetValue(PreviousTextSelectionProperty, value);
        }
    
        private static TextSelection GetPreviousTextSelection(TextBox element)
        {
            return (TextSelection)element.GetValue(PreviousTextSelectionProperty);
        }
    
        private static void OnTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (UIApplication.DesignMode)
                return;
    
            var textBox = (TextBox)d;
            textBox.TextChanged += OnTextChanged;
            textBox.SelectionChanged += OnSelectionChanged;
        }
    
        /// <summary>
        /// Determines whether the specified text is valid.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="inputType">Type of the input.</param>
        /// <returns>
        ///   <c>true</c> if the specified text is valid; otherwise, <c>false</c>.
        /// </returns>
        private static bool IsValid(string text, InputType inputType)
        {
            switch (inputType)
            {
            case InputType.PositiveInteger:
                int i;
                return int.TryParse(text, out i);
            case InputType.PositiveDecimal:
                decimal d;
                return decimal.TryParse(text, out d) && d >= 0;
            case InputType.PositiveNullableInteger:
                return text.IsNullOrEmpty() || IsValid(text, InputType.PositiveInteger);
            case InputType.PositiveNullableDecimal:
                return text.IsNullOrEmpty() || IsValid(text, InputType.PositiveDecimal);
            default:
                throw new ArgumentOutOfRangeException("inputType");
            }
        }
    
        private static void OnTextChanged(object sender, TextChangedEventArgs e)
        {
            var textBox = (TextBox)sender;
            var inputType = GetType(textBox);
    
            if (IsValid(textBox.Text, inputType))
            {
                SetPreviousTextSelection(textBox, new TextSelection(textBox.Text, textBox.SelectionStart, textBox.SelectionLength));
            }
            else
            {
                var textSelection = GetPreviousTextSelection(textBox);
                if (textSelection == null)
                {
                    textBox.Text = "";
                }
                else
                {
                    textBox.Text = textSelection.Text;
                    textBox.SelectionStart = textSelection.SelectionStart;
                    textBox.SelectionLength = textSelection.SelectionLength;
                }
            }
        }
    
        private static void OnSelectionChanged(object sender, RoutedEventArgs e)
        {
            var textBox = (TextBox)sender;
            SetPreviousTextSelection(textBox, new TextSelection(textBox.Text, textBox.SelectionStart, textBox.SelectionLength));
        }
    }
    

    然后在您的 xaml 代码中使用它(“ui:”命名空间需要解析,但是,您仍然需要做功课:)):

    <TextBox Text="{Binding MyText, Mode=TwoWay}" ui:Input.Type="PositiveNullableDecimal" />
    

    所以基本上,扩展器会记住最后一个有效状态(文本+选择)并在新结果无效时恢复它。 枚举 InputType 当然可以扩展。

    【讨论】:

    • 我没有测试过这个解决方案,但它听起来比我的要好得多,所以 +1!
    【解决方案3】:

    有什么方法可以阻止“alt + 数字组合”吗?

    不是真的。我的建议是不要打扰,看看会发生什么。

    TBH 如果你真的想构建一个数字输入控件,你不应该从TextBox 派生。您将从Control 派生并在新控件的默认控件模板中放置一个TextBox。

    说实话,我只是在Toolkit 中使用了 NumericUpDown。

    【讨论】:

      【解决方案4】:

      您只是想阻止非数字文本输入吗? this blog post 中描述的另一种方法是创建一个文本框过滤器,该过滤器可以作为附加的依赖属性添加到普通的 TextBox 中。无论哪种方式,您仍然需要在输入数据后对其进行验证,因为用户可能会粘贴无效数据。

      【讨论】:

        【解决方案5】:

        简短而甜蜜 - Alt 键的处理级别低于您的程序。

        This 文章更详细地描述了该问题,而this 链接提供了一些 c++ 代码,如果您真的想解决此问题,可以帮助您。

        【讨论】:

        • 在 SL 中你无法真正达到这种编码水平。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-10
        • 1970-01-01
        • 1970-01-01
        • 2011-10-08
        • 2011-06-10
        • 1970-01-01
        相关资源
        最近更新 更多