2016-03-08 4 views
0

Я использовал MVVM Light на некоторое время - это очень полезно и почти всегда первая библиотека, которую я добавляю в новый проект!MVVM Light ViewModelBase vs Encapsulation

Мне интересно, что будет означать разработку класса, который реализует INotifyPropertyChanged, чтобы инкапсулировать свойство bindable (пример ниже).

public class BindableProperty<T> : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 


    private T mValue; 
    public T Value 
    { 
     get { return mValue; } 
     set 
     { 
      if (!EqualityComparer<T>.Default.Equals(mValue, value)) 
      { 
       mValue = value; 
       if (PropertyChanged != null) 
       { 
        PropertyChanged(this, new PropertyChangedEventArgs("Value")); 
       } 
      } 
     } 
    } 


    public BindableProperty(T default_value) 
    { 
     mValue = default_value; 
    } 
} 

С помощью этого класса, я должен изменить свой Xaml, но я полагаю, что мой ViewModel может быть более удобным для чтения (ниже) - особенно, когда число объектов растет.

<TextBox Text="{Binding FirstName.Value, UpdateSourceTrigger=PropertyChanged}"/> 

public class MainVM 
{ 
    public BindableProperty<string> FirstName { get; private set; } 
    public BindableProperty<string> LastName { get; private set; } 

    public MainVM() 
    { 
     FirstName = new BindableProperty<string>(""); 
     LastName = new BindableProperty<string>(""); 
    } 
} 

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

Я пропустил что-то очевидное? Каковы некоторые из компромиссов для этого проекта, о которых я мог бы не знать (например, последствия изменения привязки xaml, проверки данных ...)?

+0

я, возможно, пропустили то, что вы пытаетесь получить через, но я думаю, что вы должны делать это внедрение «свойство зависимостей». –

+0

Посмотрите на реализацию класса [BindableBase] (https://github.com/PrismLibrary/Prism/blob/master/Source/Prism/Mvvm/BindableBase.cs) в структуре PRISM, и это [использование] (http://stackoverflow.com/questions/28844518/bindablebase-vs-inotifychanged). Одним из приключений является то, что вы привязываетесь к самому свойству, а не к 'property.Value'. – Batuu

+0

@Batuu - BindableBase выглядит очень похоже на mvvm-light [ViewModelBase] (http://www.mvvmlight.net/help/SL5/html/e1c28204-2508-66c2-f984-25ba65c04a30.htm). Возможно, это не стоит усилий, но с использованием этого кода шаблона обычно помещается 5 строк на каждое свойство в моей модели ViewModel, чтобы он выглядел чистым, против 1 строки с использованием класса выше (предоставлено еще 1 в конструкторе). – sfm

ответ

0

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

Этот подход не будет работать очень хорошо с проверкой ни он будет, если у вас есть свойства, которые зависят друг от друга, т.е. FirstName, LastName и FullName где FullName просто public string FullName { get { return FirstName+" "+LastName; } }.

То же самое касается валидации (с IDataErrorInfo). С базового класса ваш код выглядит

public string FirstName 
{ 
    get { return firstName; } 
    set 
    { 
     if(string.IsNullOrEmpty(value)) 
     { 
      // where errors is a Dictionary<string, string> 
      errors.Add(nameof(FirstName), "First name can't be empty."); 
      return; 
     } 

     if(value.Length <2) 
     { 
      errors.Add(nameof(FirstName), "First name must be at least 2 characters long."); 
      return 
     } 

     Set(ref firstName, value); 
     errors.Remove(nameof(FirstName)); 
    } 
} 

Это будет боль реализовать в герметизированных свойства

+0

. Я соглашаюсь на более сложные сценарии, вам нужна гибкость для написания показанного кода выше. Но для очень простых случаев, я чувствую, что этот код делает мои виртуальные машины трудными для сканирования и понимания их цели. Для меня самый простой из свойств - 7 строк (опорная переменная: 1 строка, свойство: 4 строки, интервал: 2 строки). Я думаю, что это затрудняет переваривание и быстрое понимание функции виртуальной машины. Если я использую что-то вроде класса из исходного вопроса, у меня есть 1 строка за свойство в верхней части моей виртуальной машины. – sfm