MVVM - проверка

Мы пытаемся выяснить валидацию в mvvm, выполняющем проверку в бизнес-логике или модели. Я реализовал проверку по типу исключений в нашей бизнес-логике - упрощенную схему можно найти здесь: alt text

Если у нас есть много входных данных, которые не зависят друг от друга, нет проблем, исключение вызывается, текстовое поле улавливает его, отмечает, что оно кратно для каждого неправильного ввода. Однако, когда у нас есть зависимые значения, у нас проблемы. например.

  • Значения Value1 и Value2 в модели не должны быть одинаковыми, поэтому у нас есть функция проверки достоверности в каждом из тех, кто ищет значение equals и генерирует исключение, если это произойдет

  • теперь, если мы установим Value1 в 0 и Value2 в 1, все будет хорошо

  • Значение 1 устанавливается в графическом интерфейсе в 1 → , этот цвет становится красным, потому что проверка других значений не запускается, поэтому Value2 в графическом интерфейсе не отображается с ошибкой

  • Значение Value2 получает значение 2 в графическом интерфейсе, теперь мы достигли допустимого состояния, но только Value2 получает подтверждение, поэтому Value1 по-прежнему отмечен как ошибочный

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

Вместо реализации проверки по исключению можно также реализовать интерфейс IDataErrorInfo, но проблема все еще существует, нет возможности принудительно заставлять зависящие значения снова проверять свои значения, по крайней мере, я не вижу:)

Любая помощь приветствуется

веселит,  Manni


[очистка, удаление ненужного шага]


15.11.2010 - Part2

ОК, большой переосмысленный здесь, мы собираемся с бизнес-уровнями. вот наша текущая планируемая конфигурация: alt text (изображение немного немного масштабировано здесь, пожалуйста, откройте его в отдельном окне, чтобы показать его в полном размере) все более или менее понятно, за исключением того, как уведомлять все модели viewmodels/model различных редакторов, если модель данных в бизнес-логике изменяется. один из способов сделать это - отслеживать клонированные модели в бизнес-логике, которая их создает. Когда модель данных изменяется с помощью фиксации бизнес-логики(), все остальные зарегистрированные клоны модели могут быть уведомлены об изменениях и распространять их дальше. в качестве альтернативы бизнес-логика может опубликовать событие, к которому все модели viewmodels подписываются, чтобы они также получили изменения - может ли кто-нибудь дать мне подсказку, что лучше?

Еще раз спасибо за помощь, извините, я так заблокирован;)

Ответы

Ответ 1

Вы можете использовать интерфейс System.ComponentModel.IDataErrorInfo. Этот очень удобный интерфейс дает вам возможность:

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

Вы реализуете IDataErrorInfo на своей модели viewmodel (или даже практически в своей модели базы моделей и переопределяете ее в своих производных моделях). Из-за характера привязки данных значения, которые мне нужно проверить, все они есть в модели представления, и я могу проверить любую их комбинацию. Конечно, вы все еще имеете свою проверку на своем бизнес-уровне, но вам больше не нужно совершать поездку на ваш бизнес-уровень (или модель), чтобы произвести некоторую проверку.

Вот краткий пример с экрана (WPF), который собирает некоторые детали пользователя и выполняет базовую проверку:

Код С#:

    #region IDataErrorInfo Members

    /// <summary>
    /// Gets an error message indicating what is wrong with this object.
    /// </summary>
    /// <value></value>
    /// <returns>An error message indicating what is wrong with this object. The default is an empty string ("").</returns>
    public override string Error
    {
        get
        {
            return this["UserCode"] + this["UserName"] + this["Password"] + this["ConfirmedPassword"] + this["EmailAddress"];
        }
    }

    /// <summary>
    /// Gets the <see cref="System.String"/> with the specified column name.
    /// </summary>
    /// <value></value>
    public override string this[string columnName]
    {
        get
        {
            switch (columnName)
            {
                case "UserCode":
                    if (!string.IsNullOrEmpty(UserCode) && UserCode.Length > 20)
                        return "User Code must be less than or equal to 20 characters";
                    break;

                case "UserName":
                    if (!string.IsNullOrEmpty(UserCode) && UserCode.Length > 60)
                        return "User Name must be less than or equal to 60 characters";
                    break;

                case "Password":
                    if (!string.IsNullOrEmpty(Password) && Password.Length > 60)
                        return "Password must be less than or equal to 60 characters";
                    break;

                case "ConfirmedPassword":
                    if (Password != ConfirmedPassword)
                        return Properties.Resources.ErrorMessage_Password_ConfirmedPasswordDoesntMatch; 
                    break;

                case "EmailAddress":
                    if (!string.IsNullOrEmpty(EmailAddress))
                    {
                        var r = new Regex(_emailRegex);
                        if (!r.IsMatch(EmailAddress))
                            return Properties.Resources.ErrorMessage_Email_InvalidEmailFormat;
                    }
                    break;
            }
            return string.Empty;
        }
    }

    #endregion

и вот разметка XAML для двух текстовых полей на странице (особенно обратите внимание на свойства ValidatesOnDataErrors и ValidatesOnExceptions в привязке Text):

<TextBox Name="UserCodeTextBox" 
         Text="{Binding UserCode, 
                Mode=TwoWay, 
                UpdateSourceTrigger=PropertyChanged, 
                ValidatesOnDataErrors=True, 
                ValidatesOnExceptions=True, 
                NotifyOnSourceUpdated=True, 
                NotifyOnTargetUpdated=True}" 
         GotFocus="Input_GotFocus"
         VerticalAlignment="Top"
         Margin="165,0,150,0"  
         CharacterCasing="Upper"
         />

<TextBox Name="UserNameTextBox" 
         Text="{Binding UserName, 
                Mode=TwoWay, 
                UpdateSourceTrigger=PropertyChanged, 
                ValidatesOnDataErrors=True, 
                ValidatesOnExceptions=True, 
                NotifyOnSourceUpdated=True, 
                NotifyOnTargetUpdated=True}" 
         GotFocus="Input_GotFocus"
         VerticalAlignment="Top"
         Margin="165,30,0,0"  
         />

Ответ 2

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

  • Value1 и Value2 взаимозависимы из-за условия "Value1 и Value2 в модели не должны быть одинаковыми".

  • Это означает, что при изменении Value2 Value1 также изменяется, и наоборот! Фактически, когда Value2 изменяется, результат проверки Value1 изменяется, но это близко к предыдущему утверждению.

  • Value1 и Value2 установщики должны уведомить об изменении свойств Value1 и Value2.

  • Просмотр должен перечитывать и проверять оба значения и очищать ошибочную метку.

  • Не уверен, что если WPF сделает это, если обнаружит, что событие уведомления было поднято, но значение фактически не изменилось.