locked
WPF: Validation error message for localization does not work RRS feed

  • Question

  • Our application needs to support Validation error message to be localized.

    We have tried the following code in ViewModel class to support error message to be localized.

     private string userName;
    [Required(ErrorMessageResourceName = "NameRequired", ErrorMessageResourceType = typeof(projectxx.Properties.Resources1))]
    [RegularExpression("[a-zA-Z0-9]{3,50}", ErrorMessageResourceName = "NameMinLength", ErrorMessageResourceType = typeof(projectxxx.Properties.Resources1))]
    public string UserName
    {
                set
                {
                    userName = value;
                    OnPropertyChanged("UserName");
                }
                get
                {
                    return userName;
                }
            }

    <TextBox x:Name="xUsername"

       VerticalContentAlignment="Center"

       MaxLength="20"

       Height="35"

       Style="{StaticResource ValidationStyleTextBox}"

       Text="{Binding Path=UserName, UpdateSourceTrigger=PropertyChanged,

              ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" />

    <Style x:Key="ValidationStyleTextBox"
               TargetType="{x:Type Control}">
            <Setter Property="Foreground"
                    Value="#333333" />
            <Style.Triggers>
                <Trigger Property="Validation.HasError"
                         Value="true">
                    <Setter Property="ToolTip"
                            Value="{Binding RelativeSource={RelativeSource Self},
                            Path=(Validation.Errors)[0].ErrorContent}" />
                </Trigger>
            </Style.Triggers>
        </Style>

     

    Even though the User name is empty, ValidatesOnDateErrors=True, we do not see the Red Rectangle displayed on the User Name textbox.

    However, if we try the following code, we will see the Red rectangle display on the UserName textbox and tooltip shows the error message.

    [Required(ErrorMessage = "Field 'UserName' is required.")]
            [RegularExpression("[a-zA-Z0-9]{3,50}", ErrorMessage = ""User Name must a-z and length of 3-50 characters"")]
            public string UserName
            {
                set
                {
                    userName = value;
                    OnPropertyChanged("UserName");
                }
                get
                {
                    return userName;
                }
            }

    We have searched online and found the link: http://social.msdn.microsoft.com/Forums/en-US/7798ff0f-336a-443d-97ff-55dff42617cd/attributesbased-validation-and-wpf?forum=adodotnetentityframework

    It mentioned that "My only "gripe" with it would be that because validation with IDataErrorInfo is based on this[string propertyName], every attribute has to specify an ErrorMessage parameter (returning an empty/null ErrorMessage results in WPF thinking there is no validation error). "

    In first approach, the validation attribute does not define "ErrorMessage", so it treats it as empty/null.

    [Required(ErrorMessageResourceName = "NameRequired", ErrorMessageResourceType = typeof(projectxxx.Properties.Resources1))]

    Does anyone know how to fix this problem? Thx!


    JaneC


    • Edited by JJChen Thursday, October 2, 2014 9:33 PM
    Tuesday, September 16, 2014 9:17 PM

Answers

  • We just fount out what is the problem.  We have ValidationViewModelBase which inherits from IDataErrorInfo.

    In the "public string this[string propertyName]" method we actually query/filter on "ErrorMessage"

    public class ValidationViewModelBase : IDataErrorInfo, IValidationExceptionHandler
    
    public string this[string propertyName]
            {
                get
                {
                    if (this.propertyGetters.ContainsKey(propertyName))
                    {
                        var propertyValue = this.propertyGetters[propertyName](this);
                        var errorMessages = this.validators[propertyName]
                            .Where(v => !v.IsValid(propertyValue))
                            .Select(v => v.ErrorMessage).ToArray();
    
                        return string.Join(Environment.NewLine, errorMessages);
                    }
    
                    return string.Empty;
                }
            }

    Since we do not define "ErrorMessage" in Validation attribute any more, filter on it will return nothing.

    So we have to filter on ErrorMessageResourceName. It works now.

     if (this.propertyGetters.ContainsKey(propertyName))
                    {
                        var propertyValue = this.propertyGetters[propertyName](this);
                        var errorMessages = this.validators[propertyName]
                            .Where(v => !v.IsValid(propertyValue))
                            .Select(v => v.FormatErrorMessage(v.ErrorMessageResourceName)).ToArray();
    
                        return string.Join(Environment.NewLine, errorMessages);
                    }



    JaneC

    Wednesday, September 17, 2014 12:22 AM

All replies

  • We just fount out what is the problem.  We have ValidationViewModelBase which inherits from IDataErrorInfo.

    In the "public string this[string propertyName]" method we actually query/filter on "ErrorMessage"

    public class ValidationViewModelBase : IDataErrorInfo, IValidationExceptionHandler
    
    public string this[string propertyName]
            {
                get
                {
                    if (this.propertyGetters.ContainsKey(propertyName))
                    {
                        var propertyValue = this.propertyGetters[propertyName](this);
                        var errorMessages = this.validators[propertyName]
                            .Where(v => !v.IsValid(propertyValue))
                            .Select(v => v.ErrorMessage).ToArray();
    
                        return string.Join(Environment.NewLine, errorMessages);
                    }
    
                    return string.Empty;
                }
            }

    Since we do not define "ErrorMessage" in Validation attribute any more, filter on it will return nothing.

    So we have to filter on ErrorMessageResourceName. It works now.

     if (this.propertyGetters.ContainsKey(propertyName))
                    {
                        var propertyValue = this.propertyGetters[propertyName](this);
                        var errorMessages = this.validators[propertyName]
                            .Where(v => !v.IsValid(propertyValue))
                            .Select(v => v.FormatErrorMessage(v.ErrorMessageResourceName)).ToArray();
    
                        return string.Join(Environment.NewLine, errorMessages);
                    }



    JaneC

    Wednesday, September 17, 2014 12:22 AM
  • We just fount out what is the problem.  We have ValidationViewModelBase which inherits from IDataErrorInfo.

    In the "public string this[string propertyName]" method we actually query/filter on "ErrorMessage"

    public class ValidationViewModelBase : IDataErrorInfo, IValidationExceptionHandler
    
    public string this[string propertyName]
            {
                get
                {
                    if (this.propertyGetters.ContainsKey(propertyName))
                    {
                        var propertyValue = this.propertyGetters[propertyName](this);
                        var errorMessages = this.validators[propertyName]
                            .Where(v => !v.IsValid(propertyValue))
                            .Select(v => v.ErrorMessage).ToArray();
    
                        return string.Join(Environment.NewLine, errorMessages);
                    }
    
                    return string.Empty;
                }
            }

    Since we do not define "ErrorMessage" in Validation attribute any more, filter on it will return nothing.

    So we have to filter on ErrorMessageResourceName. It works now.

     if (this.propertyGetters.ContainsKey(propertyName))
                    {
                        var propertyValue = this.propertyGetters[propertyName](this);
                        var errorMessages = this.validators[propertyName]
                            .Where(v => !v.IsValid(propertyValue))
                            .Select(v => v.FormatErrorMessage(v.ErrorMessageResourceName)).ToArray();
    
                        return string.Join(Environment.NewLine, errorMessages);
                    }



    JaneC

    Hi JJChen,

    Thank you for sharing your solutions and experience here. It will be very beneficial for other community members who have similar questions.

    Best Regards,
    Franklin


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Wednesday, September 17, 2014 5:47 AM