Не работает валидация данных в WinUI приложении

Пробую сделать валидацию вводимых данных в WinUI приложении. Пример взял отсюда. Используемый материал

XAML код страницы

<Grid>
<Grid.RowDefinitions>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
    <TextBlock Text="Login" Margin="5"/>
    <!-- InputValidationKind="Hidden" этого свойства почему то нет -->
    <TextBox 
        PlaceholderText="login"                
        Text="{x:Bind ViewModel.UserName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"                
        Margin="5"/>
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal">
    <TextBlock Text="Password" Margin="5"/>
    <TextBox
        PlaceholderText="password"
        Text="{x:Bind ViewModel.Password, Mode=TwoWay}"
        Margin="5"/>
</StackPanel>
<StackPanel Grid.Row="2" Orientation="Horizontal">
</StackPanel>
<StackPanel Grid.Row="3" Orientation="Horizontal">
    <Button 
        Content="Добавить"
        Command="{x:Bind ViewModel.AddUserCommand}"
        Margin="5"/>
</StackPanel>
</Grid>

Код ViewModel

namespace TestWinUIValidation.ViewModels;
public partial class TestViewModel : BindableBase
{    
    public TestViewModel()
    {        
        AddUserCommand = new RelayCommand(AddUser);        
    }      
    private string _userName = string.Empty;
    [MinLength(2, ErrorMessage = "Item name must be at least 2 characters.")]
    public string UserName
    {
        get => _userName;
        set => SetProperty(ref _userName, value);
    }

    private string _password = string.Empty;
    public string Password
    {
        get => _password;
        set => SetProperty(ref _password, value);
    }    
    public ICommand AddUserCommand { get; set; }
    private void AddUser()
    {
        //Здесь добавляем пользователя в модель        
    }   
}

Код BindableBase

public partial class BindableBase : INotifyPropertyChanged, INotifyDataErrorInfo, IValidatable
{
    public event PropertyChangedEventHandler? PropertyChanged;
    /// <summary>
    /// Происходит при изменении ошибок проверки для свойства или для всей сущности.
    /// </summary>
    public event EventHandler<DataErrorsChangedEventArgs>? ErrorsChanged;
    /// <summary>
    /// Этот метод устанавливает  новое значение свойства, только если оно отличается от предыдущего, 
    /// после чего вызывает OnPropertyChanged
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="originalValue"></param>
    /// <param name="newValue"></param>
    /// <param name="propertyName"></param>
    /// <returns></returns>
    protected bool SetProperty<T>(ref T originalValue, T newValue, [CallerMemberName] string propertyName = "")
    {            
        if (!EqualityComparer<T>.Default.Equals(originalValue, newValue))
        {
            originalValue = newValue;
            OnPropertyChanged(propertyName, newValue);
            return true;
        }
        return false;
    }    
    readonly Dictionary<string, List<ValidationResult>> _errors = new Dictionary<string, List<ValidationResult>>();
    /// <summary>
    /// Возвращает значение, указывающее, имеет ли сущность ошибки проверки.
    /// </summary>
    public bool HasErrors
    {
        get
        {
            return _errors.Count > 0;
        }
    }
    /// <summary>
    /// Возвращает ошибки проверки для указанного свойства или для всей сущности.
    /// </summary>
    public IEnumerable GetErrors(string propertyName)
    {
        _errors.TryGetValue(propertyName, out List<ValidationResult> errors);
        return errors;
    }
    /// <summary>
    /// Этот метод просто генерирует событие PropertyChanged, которое представление должно будет обработать
    /// </summary>
    /// <param name="propertyName"></param>        
    private void OnPropertyChanged(string propertyName, object value)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        Validate(propertyName, value);
    }
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));        
    }
    /// <summary>
    /// Добавление ошибки в справочник ошибок
    /// </summary>
    /// <param name="propertyName">Имя свойства</param>
    /// <param name="results">Объект результатов валидации</param>
    private void AddErrors(string propertyName, IEnumerable<ValidationResult> results)
    {
        if (!_errors.TryGetValue(propertyName, out List<ValidationResult> errors))
        {
            errors = new List<ValidationResult>();
            _errors.Add(propertyName, errors);
        }
        errors.AddRange(results);
        ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
    }
    private void ClearErrors(string propertyName)
    {
        if (_errors.TryGetValue(propertyName, out List<ValidationResult> errors))
        {
            errors.Clear();
            ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
        }
    }
    public void Validate(string memberName, object value)
    {
        ClearErrors(memberName);
        List<ValidationResult> results = new List<ValidationResult>();
        bool result = Validator.TryValidateProperty(
            value,
            new ValidationContext(this, null, null)
            {
                MemberName = memberName
            },
            results);
        if (!result)
        {
            AddErrors(memberName, results);
        }        
    }    
}

Интерфейс IValidatable

public interface IValidatable
{
    void Validate(string memberName, object value);
}

И при вводе неправильных данных (например одного символа), поле ввода красным не становится. Хотя в отладчике видно, что ошибка ввода зафиксирована. Не подскажете почему не работает?


Ответы (0 шт):