Паттерн MVVM делится на три части:
Модель (Model), так же, как в классическом паттерне MVC, Модель представляет собой фундаментальные данные, необходимые для работы приложения.
Вид/Представление (View) так же, как в классическом паттерне MVC, Вид — это графический интерфейс, то есть окно, кнопки и.т.п.
Модель вида (ViewModel, что означает «Model of View») является с одной стороны абстракцией Вида, а с другой предоставляет обертку данных из Модели, которые подлежат связыванию. То есть она содержит Модель, которая преобразована к Виду, а так же содержит в себе команды, которыми может пользоваться Вид, чтобы влиять на Модель.
Зачастую возникает необходимость подписываться на события представления в модели представления или переопределять его методы (например, метод OnNavigatedFrom или OnNavigatedTo). Так как сам шаблон пропагандирует разделение логики и представления, писать в code behind уж очень не хочется.
Хочу продемонстрировать небольшой ToolKit, который можно взять за основу в небольших проектах, и немного облегчить процесс разработки.
Создаем базовый класс модели представления
public class BaseViewModel : INotifyPropertyChanged
{
#region Public Properties
public ProgressivePhoneApplicationPage View { get; set; }
#endregion
#region Public Methods
public void SetView(ProgressivePhoneApplicationPage view)
{
View = view;
View.Loaded += OnViewLoaded;
View.Unloaded += OnViewUnloaded;
View.NavigatedTo += OnNavigatedTo;
View.NavigatedFrom += OnNavigatedFrom;
}
public virtual void OnNavigatedTo(NavigationEventArgs args) { }
public virtual void OnNavigatedFrom(NavigationEventArgs args) { }
public virtual void OnViewUnloaded(object sender, RoutedEventArgs e) { }
public virtual void OnViewLoaded(object sender, RoutedEventArgs e) { }
#endregion
#region Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public void NotifyPropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
ProgressivePhoneApplicationPage — это переопределенный класс PhoneApplicationPage, в котором реализован механизм поиска модели представления.
SetView() — метод для установки ссылки на представление, в модели представления.
Переопределяем класс PhoneApplicationPage
public class ProgressivePhoneApplicationPage : PhoneApplicationPage
{
public ProgressivePhoneApplicationPage()
{
DataContext = ViewModelFactory.Create(this);
}
public event Action NavigatedTo = delegate { };
public event Action NavigatedFrom = delegate { };
protected override void OnNavigatedTo(NavigationEventArgs e)
{
NavigatedTo(e);
base.OnNavigatedTo(e);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
NavigatedFrom(e);
base.OnNavigatedFrom(e);
}
}
В конструкторе мы используем класс-фабрику ViewModelFactory, задачей которого является поиск модели представления. Поиск осуществляется очень просто, если модель у нас называется LoginView, то соответствующий ей класс модели представления будем называть LoginViewModel. Это и будет критерием поиска.
Создаем класс фабрику для создания модели представления
public class ViewModelFactory
{
public static object Create(ProgressivePhoneApplicationPage view)
{
var viewModelType = FindViewModelType(view.GetType().Name);
if (viewModelType == null)
{
return new object();
}
object result = Activator.CreateInstance(viewModelType);
var methodInfo = result.GetType().GetMethod("SetView");
methodInfo.Invoke(result, new object[] { view });
return result;
}
}
Метод FindViewModelType, как видно из названия, будет искать тип модели представления в сборках приложения.фыв
Использование подобной конструкции позволяет нам в модели представления иметь ссылку на само представления, а так же привязывать контекст данных представления.Википедия