Search code examples
c#wpfwpf-styleinotifydataerrorinfo

Error message displays only the first character from the error message. INotifyDataErrorInfo WPF


I have a simple validation to show an error message when a TextBox is empty. The problem is with the message displaying the only the first letter of the message.

enter image description here

In the TextBox Style:

<Trigger Property="Validation.HasError" Value="True">
    <Setter Property="ToolTip" Value="{Binding Path=(Validation.Errors)[0].ErrorContent, RelativeSource={x:Static RelativeSource.Self}}" />
</Trigger>

If I set the error message directly to the Setter Value, it shows all of it without any problem.

<Trigger Property="Validation.HasError" Value="True">
    <Setter Property="ToolTip" Value="This field is required!" />
</Trigger>

XAML Code:

<TextBox Text="{Binding Name, Mode=TwoWay,
                UpdateSourceTrigger=PropertyChanged, 
                ValidatesOnNotifyDataErrors=True,
                NotifyOnValidationError=True}" />

C# code

private readonly Dictionary<string, string> _errors = new Dictionary<string, string>();
private readonly object _lock = new object();
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

public IEnumerable GetErrors(string propertyName)
{
    string errorsForName;
    lock (_lock)
    {
        errorsForName = _errors.FirstOrDefault(e => e.Key == propertyName).Value;//.TryGetValue(propertyName, out errorsForName);
    }
    return errorsForName;
}

public bool HasErrors
{
    get { return _errors.Values.FirstOrDefault(l => !String.IsNullOrEmpty(l)) != null; }
}

private void RaiseErrorsChanged(string propertyName)
{
    EventHandler<DataErrorsChangedEventArgs> handler = ErrorsChanged;
    if (handler == null) return;
    var arg = new DataErrorsChangedEventArgs(propertyName);
    handler.Invoke(this, arg);
}

private void RequiredValidation(string propertyName, string value)
{
    lock (_lock)
    {
        if (String.IsNullOrWhiteSpace(value))
        {
            _errors[propertyName] = "The name can't be null or empty.";
        }
        else
        {
            if (_errors.ContainsKey(propertyName)) { _errors.Remove(propertyName); }
        }

        RaiseErrorsChanged(propertyName);
        SaveCommand.RaiseCanExecuteChanged();
    }
}

Solution

  • Your GetErrors method should return an IEnumerable<string> instead of an IEnumerable<char>:

    public IEnumerable GetErrors(string propertyName)
    {
        string errorsForName;
        lock (_lock)
        {
            errorsForName = _errors.FirstOrDefault(e => e.Key == propertyName).Value;//.TryGetValue(propertyName, out errorsForName);
        }
        return new List<string> { errorsForName };
    }