在WPF中取消验证错误时的TextBox输入

M. *_*ley 3 validation wpf textbox

我试图弄清楚如何在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>
Run Code Online (Sandbox Code Playgroud)

我的自定义验证规则如下所示:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我有一个错误处理程序...我能用它做什么吗?

private void OnSomeTextBoxValidationError(object sender, ValidationErrorEventArgs e)
{
    // Can I do anything here?
}
Run Code Online (Sandbox Code Playgroud)

如果可能,请提供原始答案,而不是引用URL.我已经阅读了许多涉及事件处理程序的可能解决方案,但我没有遇到任何人讨论在我的所有验证中进行验证的可能性ValidationRule.

M. *_*ley 6

经过大量研究后,似乎完全控制输入的唯一方法TextBox是直接处理多个事件.根据C#2008中的WPF食谱(第1版,第169页):

不幸的是,没有简单的方法(目前)将有用的高级数据绑定功能与低级键盘处理相结合,这是防止用户完全键入无效字符所必需的.

以下是我创建的十六进制数字TextBox,它只接受字符af,AF和0-9.

SomeClass.xaml

<TextBox
    x:Name="SomeTextBox"
    LostFocus="TextBoxLostFocus"
    PreviewKeyDown="TextBoxPreviewKeyDown"
    PreviewTextInput="TextBoxPreviewTextInput" />
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)