Почему не хорошо выставлять Model через ViewModel в Silverlight MVVM? - PullRequest
8 голосов
/ 04 ноября 2010

Поскольку я разрабатываю приложение WPF с MVVM, я никогда не представляю модель через открытую собственность viewmodel. Во всяком случае, после того, как я только что пришел в мир Silverlight и WCF RIA, я нашел новый метод для проверки данных, который называется атрибутом Required. (есть и другие атрибуты)

На этот раз вместо создания логики валидации внутри viewmodel, я могу сделать почти логику валидации внутри самой модели.

public class TestUserPM {
    [Key]
    public int ID { get; set; }

    [Required]
    public string FirstName { get; set; }

    [Required]
    public string Email { get; set; }
}

После этого все, что мне нужно во ViewModel, это выставить открытое свойство типа TestUserPM и позволить привязке View напрямую к модели.

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

Есть ли недостатки этого метода?

Обновление 1

Я только что нашел 1 обратную сторону, может быть, там есть решение. Я хочу связать команду кнопки, например, кнопку сохранить в команду в ViewModel, но эта кнопка может выполняться тогда и только тогда, когда вся информация действительна. Из моего опыта работы с WPF MVVM, у которого есть вспомогательный класс, я назову OnCanExecuteChanged() внутри public string this[string columnName] из IDataErrorInfo.

Как мне справиться с такого рода требованиями?

Ответы [ 5 ]

10 голосов
/ 04 ноября 2010

Я все время выставляю модель через ViewModel, просто для простоты и не повторяюсь (СУХОЙ).

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

т.е.: ViewModel является DataContext и имеет свойство Model, возвращающее модель

<TextBlock Text={Binding Path=Model.Name} />
<TextBlock Text={Binding Path=Model.Address} />
5 голосов
/ 04 ноября 2010

Основная проблема, которую я вижу, заключается в том, что ваша модель (которая может быть бизнес-объектом) должна адаптироваться к пользовательскому интерфейсу. Это может повлиять на многие другие пользовательский интерфейс или бизнес-уровень.

Вы можете представить несколько пользовательских интерфейсов с разными уровнями проверки для одного и того же объекта. Это невозможно с вашим примером.

4 голосов
/ 11 ноября 2010

Проблема в том, что другие говорили, что вы не можете адаптироваться к представлению.Однако я часто хочу не повторяться - как сказал Эдуардо и с моделью, к которой можно привязаться.Я нахожу это решение немного непоследовательным, когда вы хотите изменить значение для представления - тогда некоторые будут связывать «Model.Name», а другие просто «Имя» для измененного свойства - а некоторые сценарии просто не будутработать таким образом.

Мое решение состоит в том, чтобы создать класс ViewModelProxy, в который вы можете перенаправлять свойства из другого класса и получать уведомления о свойствах бесплатно.Это делается довольно просто путем получения DynamicObject (я пропустил уведомление о коде, IDataerror и т. Д.).Круто то, что все свойства из Data перенаправляются - если вы реализуете / переопределяете свойство, с которым будете связаны, - таким образом, вам не нужно повторять код, и у вас есть разумная вещь для использования DynamicObject.*

public class ViewModelProxy<T> : DynamicObject, INotifyPropertyChanged

public T Data { get; set; }

private PropertyInfo[] objectProperties;
private PropertyInfo[] ObjectProperties
{
  get
  {
    if (objectProperties == null)
      objectProperties = typeof(T).GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
    return objectProperties;
  }
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
  var pinfo = ObjectProperties.FirstOrDefault((pi) => pi.Name == binder.Name);

  if (pinfo != null)
  {
    result = Data != null ? pinfo.GetValue(Data, null) : null;
    return true;
  }
  else
    return base.TryGetMember(binder, out result);
}


public override bool TrySetMember(SetMemberBinder binder, object value)
{
  var pinfo = ObjectProperties.FirstOrDefault((pi) => pi.Name == binder.Name);

  if (pinfo != null)
  {
    if (Data != null)
      pinfo.SetValue(Data, value, null);
    RaisePropertyChanged(binder.Name);
    return true;
  }
  else
    return base.TrySetMember(binder, value);
}

}

1 голос
/ 11 ноября 2010

Чтобы выставить модель во ViewModel, вам нужно подготовить вашу модель для адаптации вида, таким образом, вы должны загрязнить вашу модель определенным кодом вида:

  • Уведомить об изменении свойства поддержки
  • Поддержка информации об ошибках данных (проверка внутри)
  • Редактируемая поддержка.

Необходимо не загрязнять вашу модель другими вещами, идеальная модель должна иметь минимальные зависимости с другой библиотекой, поэтому ее можно использовать в одном приложении с другой платформой (asp.net, mobile, mono, winform, wpf так далее). Или для обновления / понижения.

в любом случае ..

Я сделал небольшое приложение WPF (еще не завершено), я использовал uNhAddins, NHibernate, Castle для его создания. Я не говорю, что это было лучшее решение, но я действительно рад работать с ним. Сначала проверьте код, а затем посмотрите разделение сущности, логики проверки и бизнес-логики. Разделение сборок было разработано так, чтобы минимизировать зависимость между основным приложением, пользовательским интерфейсом и логикой приложения.

1 голос
/ 04 ноября 2010

Вы можете использовать проверку с помощью аннотации в Silverlight, а не заполнять ViewModel кодом.

В случае каких-либо специальных правил проверки вы можете создавать собственные средства проверки и украшать элементы с помощью [CustomValidation ...], что опять-таки не допустит проверки к ViewModel.

В любом случае описываемые вами бизнес-правила обычно являются общими для представлений.Специальная проверка для особых случаев может быть добавлена ​​в контроллеры.

В целом: ViewModel - это относительно тупой объект для хранения значений для представления.Если вы начинаете находить, что добавляете логику, обработчики событий и прочее, вам, вероятно, следует взглянуть на представление объекта контроллера ... даже если в MVVM нет C:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...