WPF / MVVM中的自定义错误消息

时间:2012-11-15 11:23:45

标签: wpf mvvm

我阅读了大部分文章,我很高兴我可以使用属性(使用 IDataErrorInfo )进行验证。那很棒。但是我浪费了几个小时仍然没有很好的解决方案,以便在 IDataErrorInfo 因为强制转换失败而未触发的情况下显示自定义消息。无论出现什么错误,它都没有意义,我想翻译它。 Image

我应该应用自定义转换器还是自定义验证规则?

4 个答案:

答案 0 :(得分:1)

您可以查看此博文:http://wpfglue.wordpress.com/2012/05/06/checking-property-types-automatically/

它包含有关如何设置ValidationRules的示例,以便在类型转换错误发生之前捕获它们,并将其转换为有意义的本地化错误消息。 IDataErrorInfo在这里不会帮助你,除非你真的想按照建议将所有属性包装成字符串,这是我不想做的。原因是只有在绑定对象上设置属性成功后才会查询IDataErrorInfo,如果类型不匹配则不会发生。

答案 1 :(得分:0)

我现在不知道你是如何做验证的。但请考虑使用IDataErrorInfo接口。

你可以在这里找到一个例子

http://codeblitz.wordpress.com/2009/05/08/wpf-validation-made-easy-with-idataerrorinfo/

答案 2 :(得分:0)

我在我的viewmodels中使用字符串属性,所以我可以使用idataerrorinfo处理每个输入。当然,我必须在调用服务时将我的字符串属性解析为正确的类型,或者将值放到我的模型中。

另一种方法是在视图中禁止输入。例如。只使用数字文本框。

或使用行为(Blend Sdk),如:

<TextBox Text="{Binding MyDecimalProperty}">
        <i:Interaction.Behaviors>
            <Behaviors:TextBoxInputBehavior InputMode="DecimalInput"/>
        </i:Interaction.Behaviors>
 </TextBox>

的.cs

public class TextBoxInputBehavior : Behavior<TextBox>
{
    const NumberStyles validNumberStyles = NumberStyles.AllowDecimalPoint |
                                               NumberStyles.AllowThousands |
                                               NumberStyles.AllowLeadingSign;
    public TextBoxInputBehavior()
    {
        this.InputMode = TextBoxInputMode.None;
    }

    public TextBoxInputMode InputMode { get; set; }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.PreviewTextInput += AssociatedObjectPreviewTextInput;
        AssociatedObject.PreviewKeyDown += AssociatedObjectPreviewKeyDown;

        DataObject.AddPastingHandler(AssociatedObject, Pasting);

    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.PreviewTextInput -= AssociatedObjectPreviewTextInput;
        AssociatedObject.PreviewKeyDown -= AssociatedObjectPreviewKeyDown;

        DataObject.RemovePastingHandler(AssociatedObject, Pasting);
    }

    private void Pasting(object sender, DataObjectPastingEventArgs e)
    {
        if (e.DataObject.GetDataPresent(typeof(string)))
        {
            var pastedText = (string)e.DataObject.GetData(typeof(string));

            if (!this.IsValidInput(this.GetText(pastedText)))
            {
                System.Media.SystemSounds.Beep.Play();
                e.CancelCommand();
            }
        }
        else
        {
            System.Media.SystemSounds.Beep.Play();
            e.CancelCommand();
        }
    }

    private void AssociatedObjectPreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Space)
        {
            if (!this.IsValidInput(this.GetText(" ")))
            {
                System.Media.SystemSounds.Beep.Play();
                e.Handled = true;
            }
        }
    }

    private void AssociatedObjectPreviewTextInput(object sender, TextCompositionEventArgs e)
    {
        if (!this.IsValidInput(this.GetText(e.Text)))
        {
            System.Media.SystemSounds.Beep.Play();
            e.Handled = true;
        }
    }

    private string GetText(string input)
    {
        var txt = this.AssociatedObject;
        var realtext = txt.Text.Remove(txt.SelectionStart, txt.SelectionLength);
        var newtext = realtext.Insert(txt.CaretIndex, input);

        return newtext;
    }

    private bool IsValidInput(string input)
    {
        switch (InputMode)
        {
            case TextBoxInputMode.None:
                return true;
            case TextBoxInputMode.DigitInput:
                return CheckIsDigit(input);

            case TextBoxInputMode.DecimalInput:
                if (input.Contains("-"))
                    if (input.IndexOf("-") == 0 && input.LastIndexOf("-")==0)
                        return true;
                    else
                        return false;
                if (input.ToCharArray().Where(x => x == ',').Count() > 1)
                    return false;

                decimal d;
                return decimal.TryParse(input,validNumberStyles,CultureInfo.CurrentCulture, out d);
            default: throw new ArgumentException("Unknown TextBoxInputMode");

        }
        return true;
    }

    private bool CheckIsDigit(string wert)
    {
        return wert.ToCharArray().All(Char.IsDigit);
    }
}

public enum TextBoxInputMode
{
    None,
    DecimalInput,
    DigitInput
}

答案 3 :(得分:0)

如果您想自定义消息,唯一的方法是实现您自己的Validation rule。请参阅此链接以获取代码Custom Validation