Search code examples
c#wpfxamlvalidationrule

WPF - ValidationRule isn't being called


This is a follow up question to a previously asked question by me:

WPF - ValidationRule is not being called

There I was told I should implement INotifyDataErrorInfo and so I did but it still doesn't work.

Here is the xaml:

<TextBlock VerticalAlignment="Center">
            <TextBlock.Text>
                <Binding Path="Path" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
                    <Binding.ValidationRules>
                        <viewModel:StrRule/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBlock.Text>
        </TextBlock>

In the ViewModel:

private string _path;
    public string Path
    {
        set 
        { 
            _path = value;
            OnPropertyChange("Path");
        }
        get { return _path; }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChange(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private Dictionary<String, List<String>> errors = new Dictionary<string, List<string>>();
    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

    private void SetErrors(string propertyName, List<string> propertyErrors)
    {
        // Clear any errors that already exist for this property.
        errors.Remove(propertyName);
        // Add the list collection for the specified property.
        errors.Add(propertyName, propertyErrors);
        // Raise the error-notification event.
        if (ErrorsChanged != null)
            ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
    }
    private void ClearErrors(string propertyName)
    {
        // Remove the error list for this property.
        errors.Remove(propertyName);
        // Raise the error-notification event.
        if (ErrorsChanged != null)
            ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
    }

    public System.Collections.IEnumerable GetErrors(string propertyName)
    {
        if (string.IsNullOrEmpty(propertyName))
        {
            // Provide all the error collections.
            return (errors.Values);
        }
        else
        {
            // Provice the error collection for the requested property
            // (if it has errors).
            if (errors.ContainsKey(propertyName))
            {
                return (errors[propertyName]);
            }
            else
            {
                return null;
            }
        }
    }

    public bool HasErrors
    {
        get
        {
            return errors.Count > 0;
        }
    }

And the validation rule:

 public class StrRule : ValidationRule
{
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        string filePath = String.Empty;
        filePath = (string)value;
        if (String.IsNullOrEmpty(filePath))
        {
            return new ValidationResult(false, "Must give a path");
        }

        if (!File.Exists(filePath))
        {
            return new ValidationResult(false, "File not found");
        }
        return new ValidationResult(true, null);
    }
}

I also got a button which opens a FileDialog and then updates the ViewModels' Path property.

When the TextBlock is updated, the binding itself works and the set property is being called, but not the validation rule itself. What is missing/wrong here?


Solution

  • As stated in the comment ValidationRule gets called only in case binding is updated from Target(TextBlock Text) to Source(ViewModel property).

    So, instead of setting source value directly vm.FilesPath = filename;, set TextBlock Text value and validation rule Validate method will be called.