Наследование / «Компонентация» в представлениях WPF - PullRequest
1 голос
/ 12 октября 2011

Предположим, у меня есть несколько видов в моем приложении WPF, которые все показывают отчет, но каждый вид показывает свой отчет.
Я создал базовую ViewModel, которая содержит все то, что объединяет все отчеты. Каждый отчет View получает свою собственную ViewModel, производную от базовой ViewModel. Эти производные ViewModels имеют следующие обязанности:

  1. Создать данные отчета
  2. Форматирование данных отчета для печати
  3. Укажите свойства для параметров отчета
  4. Предоставить команды для дополнительных действий, которые можно выполнить в сгенерированном отчете (необязательно)

Все хорошо и кратко, однако, Представления - полный беспорядок. По сути, каждое представление одинаково с небольшими изменениями, например:

  1. Предоставляет различные элементы управления для параметров отчета
  2. Предоставляют кнопки, которые привязываются к командам для дополнительных действий

Я бы хотел добиться следующего:

  1. Иметь базовое представление, которое определяет все элементы, общие для всех представлений отчета, аналогично Site.master в ASP.NET. Он будет содержать кнопку поиска, кнопку печати, сетку, в которой отображается отчет и т. Д. *
  2. Иметь конкретные представления - по одному для каждого отчета - которые определяют только элементы управления для параметров поиска и кнопки для дополнительных действий

Как это сделать? Поиск в Google на главной странице WPF порождает множество нестандартных решений - наверняка должен быть стандартный способ?

Ответы [ 2 ]

2 голосов
/ 12 октября 2011

В WPF заполнитель ContentControl.ContentTemplate может быть установлен автоматически на основе его DataTemplate.DataType, если Content установлен на тот же экземпляр DataType.

http://www.japf.fr/2009/03/thinking-with-mvvm-data-templates-contentcontrol/

1 голос
/ 12 октября 2011

Я не уверен, что это стандартный способ создания составных представлений, но я добился определенного успеха в определении главного представления (в моем случае Window), которое содержит общие элементы управления, необходимые для семейства представленийи добавление различных UserControl для каждого отдельного вспомогательного представления в мастер с использованием ContentControl в качестве эквивалента ContentPlaceholder на главной странице ASP.NET.В моем случае я определил интерфейс, который реализуют все вложенные представления:

public interface ISubView
{
   BaseViewModel ViewModel { get; set; }
}

Это позволяет моему ApplicationController помещать модель представления в дочернее представление при обработке запроса, чтобы показать конкретное представление.,Подэпидем затем составляется с основным видом через свойство setter на главном представлении перед его отображением.

ApplicationController - это класс, который централизует задачи открытия и закрытия представлений;всякий раз, когда что-либо в приложении хочет показать конкретное представление, оно запрашивает ApplicationController.Когда он получает запрос на показ определенного представления, он ищет и создает соответствующий подвид и подкласс модели представления из внутреннего «реестра» и компонует части вместе.При запуске приложения вы создаете ApplicationController и регистрируете комбинации подкласса ViewModel и подкласса View.Частичный пример реализации:

public class ApplicationController
{

   private IDictionary<string, Tuple<Func<ISubView>, Func<BaseViewModel>> _registry;
   private Func<IShellWindow> _shellActivator;

   public ApplicationController(Func<IShellWindow> shellActivator)
   {
      _registry = new Dictionary<string, Tuple<Func<ISubView>, Func<BaseViewModel>>();
      _shellActivator = shellActivator;
   }

   public void RequestShow(string viewName)
   {
      var shell = _shellActivator(); 
      var viewToModel = _registry[viewName];
      var view = viewToModel.Item1();
      var viewModel = viewToModel.Item2();
      view.ViewModel = viewModel;
      shell.Display(view);
   }

   public Register(string name, Func<ISubView> subViewCreator, Func<ViewModel> viewModelCreator)
   {
      _registry.Add(name, new Tuple(subViewCreator, viewModelCreator));
   }
}

В методе оболочки Display (определенном в интерфейсе IShellView) вы бы сделали что-то вроде:

   public void Display(ISubView view)
   {
      contentHolder.Content = view;
      DataContext = view.ViewModel;
      Show();
   }

Запуск приложениябудет включать в себя что-то вроде:

var appController = new ApplicationController(() => new ShellWindow());
appController.Register("EmployeesReport", () => new EmployeesReportView(), () => new EmployeesReportViewModel);
appController.Register("OrdersReport", () => new OrdersReportView(), () => new OrdersReportViewModel());

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