1

I have a ViewModel in my C# WPF application which contains several properties like this one

public class ExecutionsCreateViewModel : ValidationViewModelBase
{
    [Required(ErrorMessage = "Execution name is required.")]
    [StringLength(60, ErrorMessage = "Execution name is too long.")]
    public string ExecutionName { get; set; }
    [...]
}

Thats my ValidationViewModelBase class

public abstract class ValidationViewModelBase : IDataErrorInfo
{
    string IDataErrorInfo.Error
    {
        get
        {
            throw new NotSupportedException("IDataErrorInfo.Error is not supported.");
        }
    }
    string IDataErrorInfo.this[string propertyName]
    {
        get
        {
            if (string.IsNullOrEmpty(propertyName))
            {
                throw new ArgumentException("Invalid property name", propertyName);
            }
            string error = string.Empty;
            var value = GetValue(propertyName);
            var results = new List<ValidationResult>(1);
            var result = Validator.TryValidateProperty(
                value,
                new ValidationContext(this, null, null)
                {
                    MemberName = propertyName
                },
                results);
            if (!result)
            {
                var validationResult = results.First();
                error = validationResult.ErrorMessage;
            }
            return error;
        }
    }
    private object GetValue(string propertyName)
    {
        PropertyInfo propInfo = GetType().GetProperty(propertyName);
        return propInfo.GetValue(this);
    }
}

And this is my TextBox in XAML

<TextBox Text="{Binding ExecutionName, UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}"/>

Attributes are working, UI is correctly notified when property becomes invalid ("Invalid" VisualState is triggered).

The problem is, I don't know how to check in Create method if certain property is currently valid or not.

private void Create()
{
    if(/*check if property is invalid*/)
    {
        MessageBox.Show(/*property ErrorMessage*/);
        return;
    }

    //Do something with valid properties
}}

I've tried with Validator.ValidateProperty (1, 2, 3) but it's not working and/or it's too messy. I was also doing tricks like

    try
    {
        ExecutionName = ExecutionName;
    }
    catch(Exception ex)
    {
        MessageBox.Show(ex.Message);
        return;
    }

But it's not working in some scenarios and does not look very professional. Maybe ValidateProperty is the key, but after many "tutorials" I still doesn't know how to fill it to my needs.

Also there is second small thing. Attributes always validate its properties, so when user receive fresh form the ExecutionName will always be null thus Required attribute will mark it as invalid, so that control will automatically turn red. Is there a way to skip validation at initialization?

2
  • "Is there a way to skip validation at initialization" - yep, initialize shouldn't validate anything, e.g. by setting back-fields values directly. Properties are fine for UI and user validation, though not your viewmodel nor properties are implementing notifications. Commented Sep 13, 2017 at 13:01
  • when I bind a property to XML object attribute, the property is automatically called at initialization becouse that objects attribute seek for initial value for itself. Setting Mode to OneWayToSource is not helping. When ValidatesOnDataErrors is set to true, it check the validation even on initialization Commented Sep 13, 2017 at 13:09

1 Answer 1

4

The problem is, I don't know how to check in Create method if certain property is currently valid or not.

The same way as you do in your ValidationViewModelBase class, e.g.:

private void Create()
{
    var value = this.ExecutionName; //the property to validate
    var results = new List<ValidationResult>();
    var result = Validator.TryValidateProperty(
        value,
        new ValidationContext(this, null, null)
        {
            MemberName = "ExecutionName" //the name of the property to validate
        },
        results);

    if (!result)
    {
        var validationResult = results.First();
        MessageBox.Show(validationResult.ErrorMessage);
    }

    //...
}
Sign up to request clarification or add additional context in comments.

1 Comment

That's the good way to go. I've decided to use ValidateValue and catch the exception (if occurs), then the exception Message is an ErrorMessage I need, and this way I don't need results.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.