Подтвердить что ты не робот

IDataErrorInfo - Изначально игнорируйте ошибки при первом загрузке представления

Я пытаюсь проверить класс модели, используя IDataErrorInfo, как показано ниже.

//Validators
public string this[string propertyName] {
    get {
        string error = null;

        if (propertyName == "Name") {
            error = ValidateName(); 
        }
        return error;
    }
}

Это отлично работает, за исключением того, что при первом загрузке представления он уже содержит ошибки проверки. Можно ли игнорировать/подавлять ошибки проверки при первом загрузке представления. Кроме того, распространенная практика показывает ошибки при загрузке представления и до того, как Пользователь начнет ввод данных для свойств модели.

С уважением, Nirvan.

Edit: Вот как я устанавливаю IDataErrorInfo.

<TextBox Text="{Binding Name, ValidatesOnDataErrors=True}" Grid.Row="1" Grid.Column="1" />
4b9b3361

Ответ 1

Я применил следующий подход, и он работает. В принципе, модель должна по праву записывать ошибки и добавлять их в словарь, даже если объект просто создан, и Пользователь еще не ввел текст. Поэтому я не изменил код модели или код проверки IDataErrorInfo. Вместо этого я просто установил свойство Validation.Error Template на {x: Null} изначально. Затем есть код для подключения события TextBox LostFocus, который изменяет шаблон Validation.Error обратно на то, что я использую. Чтобы добиться замены шаблонов и связать обработчик событий LostFocus со всеми TextBox в моем приложении, я использовал пару свойств зависимостей. Вот код, который я использовал.

Свойства зависимостей и код LostFocus:

    public static DependencyProperty IsDirtyEnabledProperty = DependencyProperty.RegisterAttached("IsDirtyEnabled",
             typeof(bool), typeof(TextBoxExtensions), new PropertyMetadata(false, OnIsDirtyEnabledChanged));
    public static bool GetIsDirtyEnabled(TextBox target) {return (bool)target.GetValue(IsDirtyEnabledProperty);}
    public static void SetIsDirtyEnabled(TextBox target, bool value) {target.SetValue(IsDirtyEnabledProperty, value);}

    public static DependencyProperty ShowErrorTemplateProperty = DependencyProperty.RegisterAttached("ShowErrorTemplate",
             typeof(bool), typeof(TextBoxExtensions), new PropertyMetadata(false));
    public static bool GetShowErrorTemplate(TextBox target) { return (bool)target.GetValue(ShowErrorTemplateProperty); }
    public static void SetShowErrorTemplate(TextBox target, bool value) { target.SetValue(ShowErrorTemplateProperty, value); }

    private static void OnIsDirtyEnabledChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) {
        TextBox textBox = (TextBox)dependencyObject;
        if (textBox != null) {
            textBox.LostFocus += (s, e) => {
                if ((bool) textBox.GetValue(ShowErrorTemplateProperty) == false) {
                    textBox.SetValue(ShowErrorTemplateProperty, true);
                }
            };
        }
    }

Если для свойства зависимостей IsDirtyEnabled установлено значение true, он использует обратный вызов для присоединения события TextBox LostFocus к обработчику. Обработчик просто изменяет прикрепленное свойство ShowErrorTemplate к true, которое, в свою очередь, запускает триггер стиля textbox, чтобы показать шаблон Validation.Error, когда TextBox теряет фокус.

Стили TextBox:

<Style TargetType="{x:Type TextBox}">
    <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ValidationErrorTemplate}"/>
    <Setter Property="gs:TextBoxExtensions.IsDirtyEnabled" Value="True" />
    <Style.Triggers>
        <Trigger Property="gs:TextBoxExtensions.ShowErrorTemplate" Value="false">
            <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
        </Trigger>
    </Style.Triggers>
</Style>

Это может показаться слишком большим количеством кода для простой вещи, но тогда я должен сделать это только один раз для всех текстовых ящиков, которые я использую.

С уважением, Nirvan.

Ответ 2

попытайтесь установить контекст данных ПОСЛЕ просмотра представления.

В моем случае это помогло.

Ответ 3

Вы бросаете исключение в get?

public string Name
{
    get { return _name; }
    set
    {
        _name = value;
        if (String.IsNullOrEmpty(value))
        {
            throw new ApplicationException("Customer name is mandatory.");
        }
    }
}

Ответ 4

вы устанавливаете правила в свой метод ValidateName(). ваш взгляд просто показывает ошибку:) Я предлагаю, чтобы имя было обязательным полем и должно быть заполнено пользователем, но вам не нравится красная рамка при первом просмотре представления?

Я использую два разных шаблона управления для validation.errortemplate обычный и один для обязательных полей (красный *)

thats, как я сделал это в последний раз.