Exemple #1
0
        private static void HandleInputMaskDecimalKeyDown(Key key, TextBox textbox, string mask)
        {
            var startPosition    = textbox.SelectionStart;
            var isCurrency       = mask == "$";
            var isDecimal        = mask == "%";
            var numberFormat     = CultureInfo.CurrentUICulture.NumberFormat;
            var decimalSeparator = isCurrency ? numberFormat.CurrencyDecimalSeparator : numberFormat.NumberDecimalSeparator;
            var lastInsertWasDecimalSeparator = false;
            var valueIsNegative         = false;
            var valueWasNegativeOnEnter = false;

            // Need to memorize how many digits there were to the left before this keystroke
            var allChars = textbox.Text.ToCharArray().ToList();
            var numberOfDigitsToTheLeft = 0;

            for (var charCounter = 0; charCounter < startPosition; charCounter++)
            {
                if (char.IsDigit(allChars[charCounter]) || allChars[charCounter] == '-')
                {
                    numberOfDigitsToTheLeft++;
                }
            }

            // We check if the value is negative
            if (allChars.Count > 0 && allChars[0] == '-')
            {
                valueIsNegative         = true;
                valueWasNegativeOnEnter = true;
            }

            // Special custom decimal handling
            var currencySymbol = GetInputMaskCurrencySymbol(textbox);

            if (string.IsNullOrEmpty(currencySymbol))
            {
                currencySymbol = numberFormat.CurrencySymbol;
                SetInputMaskCurrencySymbol(textbox, currencySymbol); // So we have it for later
            }
            var newChar = KeyboardHelper.GetCharFromKey(key);
            var sb      = new StringBuilder(textbox.Text);

            if (key == Key.Delete)
            {
                if (textbox.SelectionLength > 0)
                {
                    sb.Remove(startPosition, textbox.SelectionLength);
                    for (var counter = 0; counter < textbox.SelectionLength; counter++)
                    {
                        allChars.RemoveAt(startPosition);
                    }
                }
                else
                {
                    if (startPosition < sb.Length)
                    {
                        sb.Remove(startPosition, 1);
                        allChars.RemoveAt(startPosition);
                    }
                }
                if (allChars.Count == 0)
                {
                    sb.Append("0");
                }
            }
            else if (key == Key.Back)
            {
                if (textbox.SelectionLength > 0)
                {
                    sb.Remove(startPosition, textbox.SelectionLength);
                    for (var counter = 0; counter < textbox.SelectionLength; counter++)
                    {
                        allChars.RemoveAt(startPosition);
                    }
                }
                else if (startPosition > 0)
                {
                    if (startPosition - 1 < sb.Length)
                    {
                        sb.Remove(startPosition - 1, 1);
                        allChars.RemoveAt(startPosition - 1);
                        numberOfDigitsToTheLeft--;
                    }
                }
                if (allChars.Count == 0)
                {
                    sb.Append("0");
                }
            }
            else
            {
                // Need to handle selected text properly by replacing it with the new input
                if (textbox.SelectionLength > 0 && !(newChar == '-' || newChar == '+'))
                {
                    sb.Remove(startPosition, textbox.SelectionLength);
                    for (var counter = 0; counter < textbox.SelectionLength; counter++)
                    {
                        allChars.RemoveAt(startPosition);
                    }
                    if (allChars.Count == 0 && valueWasNegativeOnEnter)
                    {
                        valueWasNegativeOnEnter = false;
                        valueIsNegative         = false;
                    }
                }

                if (char.IsDigit(newChar))
                {
                    sb.Insert(startPosition, newChar);
                    numberOfDigitsToTheLeft++;
                }
                else if (GetInputMaskSupportsNegative(textbox) && newChar == '-')
                {
                    // We need to make sure that the value is negative
                    valueIsNegative = true;
                    if (!valueWasNegativeOnEnter)
                    {
                        numberOfDigitsToTheLeft++;
                    }
                }
                else if (GetInputMaskSupportsNegative(textbox) && newChar == '+')
                {
                    // We need to make sure that the value is positive
                    valueIsNegative = false;
                    if (valueWasNegativeOnEnter)
                    {
                        numberOfDigitsToTheLeft--;
                        if (numberOfDigitsToTheLeft < 0)
                        {
                            numberOfDigitsToTheLeft = 0;
                        }
                    }
                }
                else if (newChar.ToString() == decimalSeparator)
                {
                    // If there is a decimal indicator to the left, we ignore the input
                    for (var counter = 0; counter < startPosition; counter++)
                    {
                        if (allChars[counter].ToString() == decimalSeparator)
                        {
                            SystemSounds.Beep.Play();
                            return;
                        }
                    }

                    // If there already is another decimal in the string (to the right), we need to get rid of it
                    var existingDecimalPosition = -1;
                    for (var counter = startPosition; counter < allChars.Count; counter++)
                    {
                        if (allChars[counter].ToString() == decimalSeparator)
                        {
                            existingDecimalPosition = counter;
                        }
                    }
                    if (existingDecimalPosition > -1)
                    {
                        sb.Remove(startPosition, existingDecimalPosition - startPosition + 1);
                    }
                    sb.Insert(startPosition, newChar);
                    lastInsertWasDecimalSeparator = true;
                }
                else
                {
                    SystemSounds.Beep.Play();
                }
            }

            var newText = sb.ToString();

            if (isCurrency && newText.StartsWith(currencySymbol))
            {
                newText = newText.Substring(currencySymbol.Length).Trim();
            }

            if (valueIsNegative && !newText.StartsWith("-"))
            {
                newText = "-" + newText;
            }
            else if (!valueIsNegative && newText.StartsWith("-"))
            {
                newText = newText.Substring(1);
            }

            if (isDecimal && newText.EndsWith("%"))
            {
                newText = newText.Substring(0, newText.Length - 1);
            }

            decimal parsedValue;

            if (decimal.TryParse(newText, out parsedValue))
            {
                var rightFormat = isCurrency ? StringHelper.Replicate("0", numberFormat.CurrencyDecimalDigits) : GetInputMaskDecimalFractionalMask(textbox);
                newText = parsedValue.ToString(GetInputMaskDecimalCharacteristicMask(textbox) + "." + rightFormat);
                if (isCurrency)
                {
                    newText = currencySymbol + " " + newText;
                }
                if (isDecimal)
                {
                    newText += "%";
                }

                textbox.SetValue(InputMaskIsValidatingProperty, true);
                textbox.Text = newText;
                SetTextUnmasked(textbox, parsedValue.ToString("###########0." + rightFormat));
                textbox.SetValue(InputMaskIsValidatingProperty, false);

                var newCaretIndex = 0;
                var digitsFound   = 0;
                var newAllChars   = newText.ToCharArray();
                foreach (var newAllChar in newAllChars)
                {
                    if (digitsFound >= numberOfDigitsToTheLeft)
                    {
                        break;
                    }
                    if (isCurrency)
                    {
                        if (newCaretIndex > currencySymbol.Length && char.IsDigit(newAllChar))
                        {
                            digitsFound++;
                        }
                    }
                    else if (char.IsDigit(newAllChar) || newAllChar == '-')
                    {
                        digitsFound++;
                    }
                    newCaretIndex++;
                }
                if (lastInsertWasDecimalSeparator)
                {
                    newCaretIndex++;
                }
                textbox.CaretIndex = newCaretIndex;
            }
            else
            {
                SystemSounds.Beep.Play();
            }
        }
Exemple #2
0
        private static void HandleInputMaskKeyDown(object sender, KeyEventArgs e)
        {
            var textbox = sender as TextBox;

            if (textbox == null)
            {
                return;
            }

            var mask                 = GetInputMask(textbox);
            var provider             = GetMaskedTextProvider(textbox, mask);
            var startPosition        = textbox.SelectionStart;
            var startSelectionLength = textbox.SelectionLength;

            var ignoreKeys = new List <Key> {
                Key.LeftShift, Key.RightShift, Key.Tab, Key.Capital, Key.CapsLock, Key.Left, Key.Right, Key.Home, Key.End
            };

            if (ignoreKeys.Contains(e.Key))
            {
                return;
            }
            if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
            {
                return;
            }

            if (e.Key == Key.Delete)
            {
                if (startSelectionLength > 0)
                {
                    provider.RemoveAt(startPosition, startPosition + startSelectionLength);
                }
                else
                {
                    provider.RemoveAt(startPosition);
                }
            }
            else if (e.Key == Key.Back)
            {
                if (startPosition > 0)
                {
                    if (startSelectionLength > 0)
                    {
                        provider.RemoveAt(startPosition, startPosition + startSelectionLength);
                    }
                    else
                    {
                        provider.RemoveAt(startPosition - 1);
                    }
                }
            }
            else
            {
                var newChar = KeyboardHelper.GetCharFromKey(e.Key);

                // TOOO: Want to handle special scenarios when the user hits .,/ or something similar, and those are indeed in the input mask. This will make it easier to enter numeric values and dates in natural fashion.
                var specialChars = new List <char> {
                    '.', ',', '-', '/', '\\', '(', ')'
                };
                if (specialChars.Contains(newChar) && textbox.CaretIndex < mask.Length)
                {
                    // We found a special character that may require special handling.
                    var remainingMask = mask.Substring(textbox.CaretIndex);
                    var shiftDistance = remainingMask.IndexOf(newChar);
                    if (shiftDistance > -1)
                    {
                        // We have discovered a keystroke with a special meaning, so we simply move the cursor to that position and carry on
                        if (newChar == '.' || newChar == ',')
                        {
                            // We handle this as a numeric entry, which means we have to clear out all the characters between the current location and the special char
                            provider.RemoveAt(startPosition, startPosition + shiftDistance);
                            provider.InsertAt(" ".Replicate(shiftDistance), 0);
                            textbox.SetValue(InputMaskIsValidatingProperty, true);
                            textbox.Text = provider.ToDisplayString();
                            textbox.SetValue(InputMaskIsValidatingProperty, false);
                        }
                        textbox.CaretIndex += shiftDistance + 1;
                        e.Handled           = true;
                        return;
                    }
                }

                if (startSelectionLength > 0) // Looks like we are in replace mode
                {
                    provider.RemoveAt(startPosition, startPosition + startSelectionLength);
                }

                provider.InsertAt(newChar, startPosition);
                textbox.SetValue(InputMaskIsValidatingProperty, true);
                textbox.Text = provider.ToDisplayString();
                textbox.SetValue(InputMaskIsValidatingProperty, false);
                var newCaretPosition = provider.FindAssignedEditPositionFrom(startPosition, true);
                newCaretPosition++;
                if (newCaretPosition > textbox.Text.Length - 1)
                {
                    newCaretPosition = textbox.Text.Length - 1;
                }
                if (newCaretPosition < 0)
                {
                    newCaretPosition = textbox.CaretIndex > 0 ? textbox.Text.Length : 0;
                }
                textbox.CaretIndex = newCaretPosition;

                e.Handled = true;
            }
        }
Exemple #3
0
        private static void HandleInputMaskKeyDown(object sender, KeyEventArgs e)
        {
            if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
            {
                return;
            }
            if (Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt))
            {
                return;
            }

            var ignoreKeys = new List <Key> {
                Key.LeftShift, Key.RightShift, Key.Tab, Key.Capital, Key.CapsLock, Key.Left, Key.Right, Key.Home, Key.End, Key.LeftAlt, Key.RightAlt, Key.LeftCtrl, Key.RightCtrl
            };

            if (ignoreKeys.Contains(e.Key))
            {
                return;
            }

            var textbox = sender as TextBox;

            if (textbox == null)
            {
                return;
            }

            var mask = GetInputMask(textbox);

            if (mask == "d" || mask == "$" || mask == "%")
            {
                HandleInputMaskDecimalKeyDown(e.Key, textbox, mask);
                e.Handled = true;
            }
            else
            {
                var startPosition = textbox.SelectionStart;

                // We are using the default .NET MaskedTextProvider to provide this functionality
                var provider = GetMaskedTextProvider(textbox, mask);

                // Need to handle selected text properly by replacing it with the new input

                if (e.Key == Key.Delete)
                {
                    if (textbox.SelectionLength > 0)
                    {
                        provider.RemoveAt(startPosition, startPosition + textbox.SelectionLength - 1);
                    }
                    else
                    {
                        provider.RemoveAt(startPosition);
                    }
                }
                else if (e.Key == Key.Back)
                {
                    if (startPosition > 0 || textbox.SelectionLength > 0)
                    {
                        if (textbox.SelectionLength > 0)
                        {
                            provider.RemoveAt(startPosition, startPosition + textbox.SelectionLength - 1);
                        }
                        else
                        {
                            provider.RemoveAt(startPosition - 1);
                        }
                    }
                }
                else
                {
                    if (textbox.SelectionLength > 0)
                    {
                        provider.RemoveAt(startPosition, startPosition + textbox.SelectionLength - 1);
                    }
                    var newChar = KeyboardHelper.GetCharFromKey(e.Key);
                    if (provider.MaskFull)
                    {
                        provider.RemoveAt(provider.Length - 1);
                    }
                    provider.InsertAt(newChar, startPosition);
                    textbox.SetValue(InputMaskIsValidatingProperty, true);
                    textbox.Text = provider.ToDisplayString();
                    textbox.SetValue(InputMaskIsValidatingProperty, false);
                    var newCarotPosition = provider.FindAssignedEditPositionFrom(startPosition, true);
                    newCarotPosition++;
                    if (newCarotPosition > textbox.Text.Length - 1)
                    {
                        newCarotPosition = textbox.Text.Length - 1;
                    }
                    if (newCarotPosition < 0)
                    {
                        newCarotPosition = textbox.CaretIndex > 0 ? textbox.Text.Length : 0;
                    }
                    textbox.CaretIndex = newCarotPosition;
                    e.Handled          = true;
                }
                textbox.SetValue(InputMaskIsValidatingProperty, true);
                SetTextUnmasked(textbox, provider.ToString(false, false));
                textbox.SetValue(InputMaskIsValidatingProperty, false);
            }
        }