Отмена ввода TextBox при ошибке проверки в WPF - PullRequest
3 голосов
/ 03 февраля 2010

Я пытаюсь выяснить, как отменить ввод пользователя в TextBox, когда происходит ошибка проверки. Если пользователь пытается ввести недопустимый символ, я бы хотел запретить его добавление в TextBox.

.

Как добавить или изменить приведенный ниже код, чтобы TextBox не мог принимать недопустимые символы? Возможно ли это без прослушивания события TextBox.TextChanged?

Мой TextBox выглядит так:

<TextBox Validation.Error="OnSomeTextBoxValidationError">
    <TextBox.Text>
        <Binding Path="Value" NotifyOnValidationError="True" UpdateSourceTrigger="PropertyChanged">
            <Binding.ValidationRules>
                 <local:SomeValidationRule />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

Мое пользовательское правило проверки выглядит так:

public class SomeValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        string hex_string = value as string;
        Match invalid_chars = Regex.Match(hex_string, "[^0-9a-fA-F]");
        bool is_valid = (invalid_chars.Success == false);
        string error_context = null;

        if (is_valid == false)
        {
            error_context = "Invalid characters";
        }

        return new ValidationResult(is_valid, error_context);
    }
}

У меня есть обработчик ошибок ... я могу с ним что-нибудь сделать?

private void OnSomeTextBoxValidationError(object sender, ValidationErrorEventArgs e)
{
    // Can I do anything here?
}

Пожалуйста, предоставьте оригинальный ответ, если это возможно, вместо ссылки на URL. Я прочитал много возможных решений, связанных с обработчиками событий, но я не встречал никого, кто бы обсуждал возможность выполнения всей моей проверки в ValidationRule.

Ответы [ 3 ]

6 голосов
/ 03 февраля 2010

После долгих исследований кажется, что единственный способ получить полный контроль над входом в TextBox - это напрямую обрабатывать несколько событий. Согласно WPF Recipes in C # 2008 (1-е изд., Стр. 169):

К сожалению, в настоящее время нет простого способа (в настоящее время) объединить полезную высокоуровневую функцию привязки данных с низкоуровневой обработкой клавиатуры, которая была бы необходима, чтобы полностью запретить пользователю вводить недопустимые символы.

Вот что я придумал, чтобы создать шестнадцатеричное число TextBox, которое принимает только символы a-f, A-F и 0-9.

SomeClass.xaml

<TextBox
    x:Name="SomeTextBox"
    LostFocus="TextBoxLostFocus"
    PreviewKeyDown="TextBoxPreviewKeyDown"
    PreviewTextInput="TextBoxPreviewTextInput" />

SomeClass.xaml.cs

private string mInvalidCharPattern = "[^0-9a-fA-F]";

// In my case SomeClass derives from UserControl
public SomeClass()
{
    DataObject.AddPastingHandler(
        this.SomeTextBox,
        new DataObjectPastingEventHandler(TextBoxPasting));
}

private void TextBoxLostFocus(object sender, RoutedEventArgs e)
{
    // You may want to refresh the TextBox's Text here. If the user deletes
    // the contents of the TextBox and clicks off of it, then you can restore
    // the original value.
}

// Catch the space character, since it doesn't trigger PreviewTextInput
private void TextBoxPreviewKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Space) { e.Handled = true; }
}

// Do most validation here
private void TextBoxPreviewTextInput(object sender, TextCompositionEventArgs e)
{
    if (ValidateTextInput(e.Text) == false) { e.Handled = true; }
}

// Prevent pasting invalid characters
private void TextBoxPasting(object sender, DataObjectPastingEventArgs e)
{
    string lPastingText = e.DataObject.GetData(DataFormats.Text) as string;
    if (ValidateTextInput(lPastingText) == false) { e.CancelCommand(); }
}

// Do the validation in a separate function which can be reused
private bool ValidateTextInput(string aTextInput)
{
    if (aTextInput == null) { return false; }

    Match lInvalidMatch = Regex.Match(aTextInput, this.mInvalidCharPattern);
    return (lInvalidMatch.Success == false);
}
1 голос
/ 03 февраля 2010

Вы, наверное, уже видели это, но это самое простое решение и всегда работало для меня. Я ловлю событие PreviewKeyDown и ..

<TextBox PreviewKeyDown="TextBox_PreviewKeyDown" Width="150" Height="30"></TextBox>

private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
    ... validation here, eg. to stop spacebar from being pressed, you'd use:

    if (e.Key == Key.Space) e.Handled = true;

}
0 голосов
/ 20 января 2015

Я использую это для приложения Windows Phone Runtime 8.1, чтобы разрешить только определенные символы:

<TextBox x:Name="TextBoxTitle" 
                 MaxLength="24" 
                 InputScope="AlphanumericHalfWidth" 
                 TextChanged="TextBoxTitle_TextChanged"                      
                 KeyUp="TextBoxTitle_KeyUp"
                 Paste="TextBoxTitle_Paste"/>

using System.Text.RegularExpressions;

bool textBoxTitle_TextPasted = false;
private void TextBoxTitle_Paste(object sender, TextControlPasteEventArgs e)
{
    textBoxTitle_TextPasted = true;
}

// only allow characters A-Z, a-z, numbers and spaces
private void TextBoxTitle_TextChanged(object sender, TextChangedEventArgs e)
{
    string fileNameCompatibleString = Regex.Replace(TextBoxTitle.Text, "[^a-zA-Z0-9\x20]", String.Empty);
    if (TextBoxTitle.Text != fileNameCompatibleString)
    {
        if (textBoxTitle_TextPasted)
        {
            TextBoxTitle.Text = fileNameCompatibleString;
            TextBoxTitle.SelectionStart = fileNameCompatibleString.Length;
        }
        else
        {
            int selectionStartSaved = TextBoxTitle.SelectionStart;
            TextBoxTitle.Text = fileNameCompatibleString;
            TextBoxTitle.SelectionStart = selectionStartSaved-1;
        }               
    }
    textBoxTitle_TextPasted = false;
}

// close SIP keyboard on enter key up
private void TextBoxTitle_KeyUp(object sender, KeyRoutedEventArgs e)
{
    if (e.Key == Windows.System.VirtualKey.Enter)
    {
        Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow.IsInputEnabled = false;
        Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow.IsInputEnabled = true;
        e.Handled = true;
    }       
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...