Winforms MaskedTextBox - переформатирование вставленного текста в соответствии с маской - PullRequest
4 голосов
/ 20 мая 2010

У меня есть элемент управления MaskedTextBox, который в нашем случае собирает номера социального страхования (налога) (без ValidatingType, хотя, начиная с представления строки, включая литералы маски). Номер социального страхования состоит из 3 групп по 3 цифры, разделенных тире. Иногда вместо черточек можно вводить или вводить пробелы.

Конфигурация текстового поля:

  • Маска: 999-999-999
  • ValidationType: null / не требуется
  • SkipLiterals: true
  • CutCopyMaskFormat: IncludeLiterals (актуально только при вырезании / копировании из текстового поля FROM)
  • TextMaskFormat: IncludeLiterals

- Дайте мне знать, если есть другие свойства, которые, по вашему мнению, могут быть важны!

Задача

При вставке следующего номера налога "450 622 097" из-за пробелов он не соответствует маске. Таким образом, я получаю «450-62-2 9» в текстовом поле. Вклейка "450-622-097" будет успешно вставлена ​​в коробку.

Я хочу иметь возможность перехватить событие вставки, чтобы исправить его, чтобы заменить пробелы тире.

В качестве альтернативы, мы можем заставить маску принимать тире ИЛИ пробелы (но всегда выводить тире)?

Non-решения

Событие MaskInputRejected - мне кажется, что я не могу понять, что было изначально введено (то есть, что отклонено), чтобы сравнить его с тем, что находится в верхней части буфера обмена. Это просто возвращает, как это было отклонено

Подтверждение события - уже происходит после применения маски. То есть значение "450-62-2 9" теперь находится в текстовом поле.

Использовать пользовательский тип ValidatingType со статической функцией Parse - опять же, происходит после того, как маска была применена.

Обнаружение события Key-Down - тогда, если серия клавиш - Ctrl-V, тогда вручную обработайте и передайте очищенную версию текста буфера обмена. Может работать, но как насчет вставки через контекстное меню правой кнопкой мыши?

Есть еще идеи?

Ответы [ 2 ]

3 голосов
/ 21 мая 2010

Хотя это молотковое решение, у строки маски есть ограничения, и я не вижу другого пути ее обхода.Вам нужно захватить событие вставки и обработать текст, прежде чем он попадет в текстовое поле.Ниже приведен упрощенный пример

   class MyMaskedTextbox : MaskedTextBox
        {
            const int WM_PASTE = 0x0302;

            protected override void WndProc(ref Message m)
            {
                switch (m.Msg)
                {
                    case WM_PASTE:
                        if (Clipboard.ContainsText())
                        {
                            string text = Clipboard.GetText();
                            text = text.Replace(' ', '-');
//put your processing here
                            Clipboard.SetText(text);
                        }
                        break;
                }
                base.WndProc(ref m);
            }
        }
1 голос
/ 29 мая 2010

В соответствии с ответом @ anchandra и последующими комментариями здесь приведен класс, позволяющий обрабатывать текст для каждого элемента управления.

public class MyMaskedTextBox : MaskedTextBox
{
    private const int WM_PASTE = 0x0302;

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case WM_PASTE:
                if (Clipboard.ContainsText())
                {
                    string text = Clipboard.GetText();
                    var args = OnPasting(text);
                    if (args.Cancel)
                    {
                        // Swallow it up!
                        return;
                    }

                    // If value changed, then change what we'll paste from the top of the clipboard
                    if (!args.Value.Equals(text, StringComparison.CurrentCulture))
                    {
                        Clipboard.SetText(args.Value);
                    }
                }
                break;
        }
        base.WndProc(ref m);
    }

    public event EventHandler<PastingEventArgs> Pasting;

    protected virtual PastingEventArgs OnPasting(string value)
    {
        var handler = Pasting;
        var args = new PastingEventArgs(value);
        if (handler != null)
        {
            handler(this, args);
        }
        return args;
    }
}

public class PastingEventArgs : CancelEventArgs
{
    public string Value { get; set; }

    public PastingEventArgs(string value)
    {
        Value = value;
    }
}

И простое использование события Pasting для удаления пробелов согласно:

private void sinTextBox_Pasting(object sender, PastingEventArgs e)
{
    e.Value = e.Value.Replace(" ", String.Empty);
}
...