2014-12-09 2 views
1

OK, поэтому я (очень) новичок в WPF, но имею 13 лет с Win-формами, поэтому не новичок. Я пишу новую систему и решил разбить лед с помощью WPF с использованием шаблона MVP-VM, поскольку я знаком с MVP.Использование WPF xaml в событиях MVP-VM или нажмите кнопку

Теперь я также повторно использую свою собственную (составную) архитектуру с интерфейсом пользовательского интерфейса или презентационным проектом в отдельности от моделей презентаций и представлений. Одним из основных преимуществ этого подхода является то, что уровень Presenter или Base имеет всю логику представления/команды/контроллера и не имеет отношения к вопросам пользовательского интерфейса. Главная IDEA заключается в том, что этот слой не имеет никакого отношения к каким-либо сборкам UI, таким как Winforms или WPF.

ВОПРОС: В Xaml у меня есть пункт меню «Выход», который я хочу связать с моделью просмотра. Каждый пример этого, который я видел, использует ICommand .., который размещен в Presentation.core ... модель представления находится на уровне презентации и поэтому не имеет ссылки на Presentation.Core ..

Xaml до сих пор является

<Window x:Class="Homestead.Wpf.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="244" Width="490" xmlns:xcad="http://schemas.xceed.com/wpf/xaml/avalondock"> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="23"/> 
     <RowDefinition Height="*"/> 
     <RowDefinition Height="23" /> 
    </Grid.RowDefinitions> 
    <Menu Grid.Row="0"> 
     <MenuItem Header="File"> 
      <MenuItem Header="Exit" /> 
     </MenuItem> 
    </Menu> 
    <StatusBar Grid.Row="2" > 
     <StatusBarItem > 
      <TextBlock Text="{Binding Path=StatusMessage}" /> 
     </StatusBarItem> 
     <StatusBarItem HorizontalAlignment="Right" MinWidth="120"> 
      <TextBlock Text="{Binding Path=UserName}" /> 
     </StatusBarItem> 
    </StatusBar> 
</Grid> 

модель зрения до сих пор является

public class ShellViewModel : ViewModelBase 
{ 

    #region Private Variables 

    private string _status = string.Empty; 
    private string _userName; 

    #endregion 

    #region Public Properties 

    public string StatusMessage 
    { 
     get { return _status; } 
     set 
     { 
      _status = value; 
      OnPropertyChanged("StatusMessage"); 
     } 
    } 

    public string UserName 
    { 
     get { return _userName; } 
     set 
     { 
      _userName = value; 
      OnPropertyChanged("UserName"); 
     } 
    } 


    #endregion 

    #region Commands 

    // No reference to ICommand... WTF 

    #endregion 
} 
  1. находится там (без использования кода позади)
  2. Как это работает с элементами меню, добавленными во время выполнения, забавным является способ.

Должен ли я перепроектировать или сломать шаблон дизайна для использования WPF? пожалуйста, направляйте меня.

Существует одна возможность, которую я могу видеть, и это интерфейс интерфейса ViewModel, а также представление. У меня есть контроллер, который создает презентаторов, которые обычно передают ведущему реализацию представления. Т.е. типичный конструктор Presenter будет

public ErrorMessagePresenter(IErrorMessageView view) 
    { 
     View = view; 
     View.Presenter = this;    
    } 

код контроллера, таким образом,

public ErrorMessagePresenter CreateErrorPresenter() 
    { 
     return new ErrorMessagePresenter(_viewFactory.CreateErrorMessageView()); 
    } 

теперь я знаю, что это обратная, но буквально слой UI занимается только вопросами пользовательского интерфейса, все остальное, включая навигации обрабатывается в базовом слое или ниже.

ответ

2

Наиболее распространенным шаблоном в WPF является Model-View-ViewModel, шаблон, в котором презентатор был удален в пользу более знающей модели представления, которая действительно осознает такие вещи, как ICommand (который является ac ontract, разделяемый уровнем представления как способ передачи действий, и это оправдывает представление о модели представления).

Вы можете попытаться заставить приложение не использовать ICommand путем реализации поведения и триггеров данных, которые выполняют действия в модели представления на основе действий в пользовательском интерфейсе, но для этого требуется гораздо больше кодирования, а не просто привязка, и это не масштабируемым или устойчивым, если вы намерены продолжать разработку приложений WPF в будущем (или приложений Windows Store, если на то пошло, которые обычно используют MVVM).

Я рекомендую рассмотреть возможность включения фреймворка, такого как MVVM-light, в ваш проект с использованием NuGet, чтобы вы могли начать работу над основами хорошо зарекомендовавшего себя набора классов, шаблонов и утилит, которые адаптировались к WPF как технологии в течение многих лет вместо того, чтобы пытаться забить «сферическую» структуру, с которой вы знакомы, в «квадратную» полость, которая является WPF (образно говоря).

Я изучил трудный путь, когда я начал с него, что попытка принести мой опыт и привычки из WinForms в WPF приносит только неприятности, так что чем скорее вы начнете примириться с идеей о том, что большая часть того, что вы сделали не будет применяться в WPF, тем лучше для вашего психического здоровья.

Конечно, шаблоны являются шаблонами, и их можно применять по-разному во множестве сред, но реальность такова, что WPF уже имеет вилки для определенных вещей, которые работают определенным образом и пытаются идти против этого собираюсь дать вам больше работы в качестве разработчика и архитектора, поэтому лучше просто пойти с потоком и адаптироваться к наиболее распространенному способу делать вещи в мире XAML.

1

Чтобы дать вам некоторые быстрые варианты решения:

  • 1 - System.Windows.Input.ICommand доступен, если вы ориентируетесь на Portable Class Library. Это может быть возможно или не зависящим от других требований к вашему проекту, но если это вариант, действительно рекомендуется разместить все ваши модели ViewModels и «UI-таргетинг» в PCL, так как они по определению являются наиболее многоразовыми и агрегированными для платформы тип сборок, которые вы можете создать в .Net, поддерживая не только сценарии Windows .Net, но и мобильные через Xamarin.

  • 2 - Провести анализ интерфейса ICommand через инъекции зависимостей или шаблоны Locator.

  • 3: Добавить ссылку на PresentationCore.dll, но убедитесь, что вы не используете ничего, кроме ICommand оттуда.


Чтобы ответить на ваш вопрос # 2, меню: ListBoxes, ComboBoxes, TreeViews и любые другие изделия на основе элементов пользовательского интерфейса в WPF являются производными от ItemsControl класса. Он предоставляет абстрактный способ динамического генерации элементов пользовательского интерфейса из набора элементов данных.

См. this blog series для получения более подробного объяснения. ItemsControl - одна из самых мощных функций WPF, и ее освоение может быть очень полезным. Я создал всевозможные вещи, используя его из палочек для банок, в «Tagging controls» (аналогично выбору тегов StackOverflow), до шахматных досок до diagram designers

В принципе вы создадите класс с простыми свойствами, представляющими элементы меню (с текстом , изображение и ICommand, которые будут выполняться при щелчке по элементу меню) и поместить экземпляры этого класса в ObservableCollection<T>, который поддерживает привязку данных к коллекциям WPF.


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

WPF решает, что с использованием DataTemplates. См. this answer для очень простого примера использования.

На самом деле, вся концепция презентатора вообще не нужна вообще в WPF. Так как ваши представления «приклеены» к их основным ViewModels, используя DataBinding, и нет необходимости в ручном «проводе» кода или передаче данных взад и вперед.