Читайте также:
|
|
Теперь, когда MEF имеет информацию как о представлении, так и о модели представления, следует реализовать логику сопоставления, которая на основании соглашении об именовании определяет представление, соответствующее переданной модели представления.
Обычной практикой является добавление суффикса ViewModel моделям представления и суффикса View представлениям. Таким образом, имея имя типа модели представления, достаточно заменить в нем ViewModel на View, чтобы получить имя представления.
1: var view = ServiceLocator.Current.GetInstance<IView>(
2: viewModel.GetType().Name.Replace("ViewModel", "View"));
На практике часто возникает ситуация, в которой целое семейство моделей представления, объединенное в одну иерархию, соответствует единственному представлению. Например, модели представления по редактированию доменных объектов UserEditViewModel, RoleEditViewModel будут иметь общего предка EditViewModel, и обеим моделям представления должно быть сопоставлено одно представление EditView, содержащее элемент управления DataForm, предоставляющий обобщенный интерфейс редактирования объекта на основе отражения типов.
Простым решением будет создание 2 наследников для представления EditView, UserEditView и RoleEditView, не содержащих никакой логики и служащих для соблюдения соглашения о наименовании. Однако более разумно включить в логику поиска соответствия обход по всему дереву наследования, до тех пор, пока не будет найдено соответствие:
1: IView view;
2: Type viewModelType = viewModel.GetType();
3:
4: do
5: {
6: view = ServiceLocator.Current.GetInstance<IView>(
7: viewModelType.Name.Replace("ViewModel", "View"));
8:
9: if (view!= null)
10: {
11: break;
12: }
13:
14: viewModelType = viewModelType.BaseType;
15: } while (viewModelType!= null);
Для возможности повторного использования данная логика добавляется в наследника класса ContentControl, который по переданной через зависимое свойство ViewModel модели представления находит соответствующее представление и устанавливает её своим содержимым:
1: /// <summary>
2: /// Presents a View corresponding to the View Model
3: /// </summary>
4: public class ViewModelPresenter: ContentControl
5: {
6: /// <summary>
7: /// Initializes a new instance
8: /// </summary>
9: public ViewModelPresenter()
10: {
11: HorizontalContentAlignment = HorizontalAlignment.Stretch;
12: VerticalContentAlignment = VerticalAlignment.Stretch;
13: }
14:
15: // Dependency properties
16: public static readonly DependencyProperty ViewModelProperty
17: = DependencyProperty.Register(
18: "ViewModel", typeof(object), typeof(ViewModelPresenter),
19: new PropertyMetadata(null, OnViewModelPropertyChanged));
20:
21: // Private fields
22: private Type _oldViewType;
23:
24: /// <summary>
25: /// View Model to be presented
26: /// </summary>
27: public object ViewModel
28: {
29: get { return GetValue(ViewModelProperty); }
30: set { SetValue(ViewModelProperty, value); }
31: }
32:
33: private static void OnViewModelPropertyChanged(
34: DependencyObject changedObject,
35: DependencyPropertyChangedEventArgs args)
36: {
37: var contentControl = (ViewModelPresenter)changedObject;
38: contentControl.RefreshContentPresenter();
39: }
40:
41: private void RefreshContentPresenter()
42: {
43: if (ViewModel == null)
44: {
45: Content = null;
46: _oldViewType = null;
47:
48: return;
49: }
50:
51: IView view;
52: Type viewModelType = ViewModel.GetType();
53:
54: do
55: {
56: view = ServiceLocator.Current.GetInstance<IView>(
57: viewModelType.Name.Replace("ViewModel", "View"));
58:
59: if (view!= null)
60: {
61: break;
62: }
63:
64: viewModelType = viewModelType.BaseType;
65: } while (viewModelType!= null);
66:
67: if (view!= null)
68: {
69: Type viewType = view.GetType();
70:
71: if (viewType == _oldViewType && Content is IView)
72: {
73: ((IView)Content).DataContext = ViewModel;
73: }
74: else
75: {
76: view.DataContext = ViewModel;
77: Content = view;
78: _oldViewType = viewType;
79: }
80: }
81: else
82: {
83: Content = "View hasn't been found";
84: _oldViewType = null;
85: }
86: }
87: }
В данном элементе управления также реализовано простейшее кеширование: если представление не изменилось, а изменилась только модель представления, то создания нового объекта не произойдет, и новая модель представления будет назначена контекстом представления взамен старой.
Далее, в если в XAML разметке необходимо отобразить представление, соответствующее определенной модели представления, достаточно вставить элемент управления ViewModelPresenter и передать ему в зависимое свойство данную модель представления. Внутри ViewModelPresenter будет отображено представление, найденное по описанному выше алгоритму.
Дата добавления: 2015-08-13; просмотров: 86 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
IoC контейнер | | | Реализация INotifyPropertyChanged средствами аспектно-ориентированного программирования |