如果用户在文本框中输入了WPF中不允许的值,请通知用户

时间:2014-04-27 10:03:47

标签: c# wpf

我很好奇通知用户他试图输入文本框的值无效的好方法。我更喜欢在文本框上添加红色动画,以告知用户该值已被忽略,因为它无效。

但是我在TextBox中使用了一个行为,这使我能够使用正则表达式来确定哪些字符/单词是有效的,哪些不是。

我必须修改代码以获得此附加功能的方式或位置?我不太确定我的行为是否可行,因为无效输入在进入TextBox之前被取消。

通常我会检查我的ViewModel中的输入,如果它无效,我会通知我的控制器显示错误但是因为我的行为是处理这个问题我不是很确定从哪里开始。

这是我的行为:

public class AllowableCharactersTextBoxBehavior : Behavior<TextBox>
{
    public static readonly DependencyProperty RegularExpressionProperty =
        DependencyProperty.Register("RegularExpression", typeof (string),
                                    typeof (AllowableCharactersTextBoxBehavior),
                                    new FrameworkPropertyMetadata("*"));

    public string RegularExpression
    {
        get { return (string) base.GetValue(RegularExpressionProperty); }
        set { base.SetValue(RegularExpressionProperty, value); }
    }

    public static readonly DependencyProperty MaxLengthProperty =
        DependencyProperty.Register("MaxLength", typeof (int), typeof (AllowableCharactersTextBoxBehavior),
                                    new FrameworkPropertyMetadata(int.MinValue));

    public int MaxLength
    {
        get { return (int) base.GetValue(MaxLengthProperty); }
        set { base.SetValue(MaxLengthProperty, value); }
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.PreviewTextInput += OnPreviewTextInput;
        DataObject.AddPastingHandler(AssociatedObject, OnPaste);
    }

    private void OnPaste(object sender, DataObjectPastingEventArgs e)
    {
        if (e.DataObject.GetDataPresent(DataFormats.Text))
        {
            string text = Convert.ToString(e.DataObject.GetData(DataFormats.Text));

            if (!IsValid(text, true))
            {
                e.CancelCommand();
            }
        }
        else
        {
            e.CancelCommand();
        }
    }

    private void OnPreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
    {
        e.Handled = !IsValid(e.Text, false);
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.PreviewTextInput -= OnPreviewTextInput;
        DataObject.RemovePastingHandler(AssociatedObject, OnPaste);
    }

    private bool IsValid(string newText, bool paste)
    {
        return !ExceedsMaxLength(newText, paste) && Regex.IsMatch(newText, RegularExpression);
    }

    private bool ExceedsMaxLength(string newText, bool paste)
    {
        if (MaxLength == 0) return false;

        return LengthOfModifiedText(newText, paste) > MaxLength;
    }

    private int LengthOfModifiedText(string newText, bool paste)
    {
        var countOfSelectedChars = this.AssociatedObject.SelectedText.Length;
        var caretIndex = this.AssociatedObject.CaretIndex;
        string text = this.AssociatedObject.Text;

        if (countOfSelectedChars > 0 || paste)
        {
            text = text.Remove(caretIndex, countOfSelectedChars);
            return text.Length + newText.Length;
        }
        else
        {
            var insert = Keyboard.IsKeyToggled(Key.Insert);

            return insert && caretIndex < text.Length ? text.Length : text.Length + newText.Length;
        }
    }
}

我想我必须修改OnPreviewTextInput方法中的代码来表明输入是错误的。但是如何添加flash动画或其他内容呢?

1 个答案:

答案 0 :(得分:0)

为{@ 3}}设置Validation.ErrorTemplate样式,以获取一些想法。

要将控件设置为无效状态,可以使用(假设已将TextProperty绑定到viewmodel)

    private void OnPreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
    {
        e.Handled = !IsValid(e.Text, false);
        if(e.Handled)
        {
            var be = BindingOperations.GetBindingExpression(AssociatedObject, TextBox.TextProperty);
            Validation.MarkInvalid(be, new ValidationError(new DummyValidationRule(), be.ParentBinding));
        }
    }

    private class DummyValidationRule : ValidationRule
    {

        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
        {
            return new ValidationResult(false, "ErrorMessage");
        }
    }

考虑使用wpf的内置机制? this SO answer是来自Magnus Montin的博客文章,其中包含有关wpf验证的大量信息。