2

I read most of the articles and i was happy that i could use attributes (with IDataErrorInfo) for validaton. That was great. But i wasted hours and still no good solution in order to display custom messages in cases that IDataErrorInfo isnt fired because casting has failed. No matter what error appears and it makes no sense and i want to translate it. Image

Should i apply a custom convertor or a custom validation rule ?

GorillaApe
  • 3,611
  • 10
  • 63
  • 106
  • Did you implement the template for that red box that contains the error message yourself? If so, what does the XAML for your error template look like? – Stephen Holt Nov 15 '12 at 11:38
  • because you like it or because it helps ? It is simillar to a question here silverlight error template question. I just did some mods to it :) and i have a comment there http://stackoverflow.com/a/7437765/294022 – GorillaApe Nov 15 '12 at 11:45
  • Maybe I misunderstood your question. Is it that you want to replace the text "Value 'gg' could not be converted"? Or something else. I asked about the error template because if you want to replace the text then that's where you'd do it... – Stephen Holt Nov 15 '12 at 11:51
  • yes i want to replace this text that is auto generated – GorillaApe Nov 15 '12 at 12:14
  • Well the text is autogenerated, but presumably you still put it there yourself using a binding along the lines of {Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent} ? I would alter that binding either by (a) using a different string property from your viewmodel that you can control yourself, or (b) using a value converter in the binding to convert the system's string with one of your own – Stephen Holt Nov 15 '12 at 12:19

4 Answers4

1

You might want to check out this blog post: http://wpfglue.wordpress.com/2012/05/06/checking-property-types-automatically/

It contains examples on how to set up ValidationRules so that type conversion errors are caught before they happen, and are translated into meaningful and localized error messages. IDataErrorInfo won't help you here, unless you really want to wrap all your properties into strings as suggested, which I wouldn't like to do. The reason is that IDataErrorInfo only is queried after setting the property on the bound object succeeded, which won't happen if the types don't match.

hbarck
  • 2,934
  • 13
  • 16
  • i'll look seems promising. String properties is a nightmare to maintain and i guess that string format is gone too. – GorillaApe Nov 15 '12 at 23:14
0

I don't know how you do Validation right now. But consider using the IDataErrorInfo Interface.

You can find an example here

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

Mohnkuchenzentrale
  • 5,745
  • 4
  • 30
  • 41
  • as i said i use IDataErrorInfo but if you put text within a textbox which is bound to a decimal/int etc you cant handle and customize this error.. – GorillaApe Nov 15 '12 at 11:28
  • aw sorry I missed that sentence. I think the ErrorInfo interface is just meant to give a notification about the error not handling the error itself. You should do this kind of validation within the inputcontrol – Mohnkuchenzentrale Nov 15 '12 at 11:31
0

i use string properties in my viewmodels, so i could handle every input with idataerrorinfo. of course i have to parse my string properties to the right type when calling a service or put the value to my model.

another way would be to forbid input in your view. eg. with numeric only textbox.

or using Behaviors(Blend Sdk) like:

<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
}
blindmeis
  • 22,175
  • 7
  • 55
  • 74
0

In case you want to customize the message, only way to do is implementing your own Validation rule. Refer to this link here for the code Custom Validation.

Community
  • 1
  • 1
Rohit Vats
  • 79,502
  • 12
  • 161
  • 185