Модель-Вид-презентатор в WinForms



Я пытаюсь реализовать метод MVP в первый раз, используя WinForms.



Я пытаюсь понять функцию каждого слоя.



в моей программе у меня есть кнопка GUI, которая при нажатии открывает окно openfiledialog.



таким образом, используя MVP, графический интерфейс обрабатывает событие нажатия кнопки, а затем вызывает presenter.openfile ();



в ведущий.openfile (), должен ли он затем делегировать открытие этого файла на уровень модели или как там нет данных или логики для обработки, он должен просто действовать на запрос и открыть окно openfiledialog?



обновление: я решил предложить щедрость, поскольку я чувствую, что мне нужна дополнительная помощь в этом, и желательно с учетом моих конкретных пунктов ниже, так что у меня есть контекст.



хорошо, после прочтения на MVP, я решил реализовать пассивный вид. Эффективно у меня будет куча элементов управления на Winform, которые будут обрабатываться Презентатором а затем задачи, делегированные модели(Ам). Мои конкретные моменты приведены ниже:




  1. когда winform загружается, он должен получить treeview. Правильно ли я думаю, что представление должно поэтому вызывать такой метод, как: presenter.gettree (), это в свою очередь делегирует модель, которая получит данные для treeview, создаст его и настроит, вернет его презентатору, который в свою очередь перейдет к представлению, которое затем просто назначит его, скажем, a панель?


  2. будет ли это то же самое для любого элемента управления данными в Winform, так как у меня также есть datagridview?


  3. мое приложение, имеет ряд классов моделей с той же сборкой. Он также поддерживает архитектуру плагинов с плагинами, которые должны быть загружены при запуске. Будет ли представление просто вызывать метод presenter, который, в свою очередь, вызовет метод, который загружает плагины и отображает информацию в представлении? Какой уровень затем будет контролировать ссылки на Плагины. Бы просмотреть ссылки на них или ведущий?


  4. правильно ли я думаю, что представление должно обрабатывать каждую вещь о представлении, от цвета узла treeview, до размера datagrid и т. д.?



Я думаю, что они мои основные проблемы, и если я понимаю, как поток должен быть для них я думаю, что я буду в порядке.

717   3  

3 ответов:

это мой скромный взгляд на MVP и ваши конкретные вопросы.

первый все, что пользователь может взаимодействовать с, или просто быть показано, является view. Законы, поведение и характеристики такого представления описываются с помощью интерфейс. Этот интерфейс может быть реализован с помощью пользовательского интерфейса WinForms, пользовательского интерфейса консоли, веб-интерфейса или даже без пользовательского интерфейса вообще (обычно при тестировании докладчика) - конкретная реализация просто не имеет значения, пока она подчиняется законам своего вида интерфейса.

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

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

последствия третий являются:

  • у презентатора нет методов, которые может вызвать представление, но в представлении есть события, на которые может подписаться презентатор.
  • ведущий знает свое мнение. Я предпочитаю делать это с помощью инъекции конструктора на конкретного ведущего.
  • представление не имеет понятия, какой презентатор управляет им; он просто никогда не будет предоставлен ни одному презентатору.

для вашего вопроса, выше может выглядеть так в несколько упрощенном коде:

interface IConfigurationView
{
    event EventHandler SelectConfigurationFile;

    void SetConfigurationFile(string fullPath);
    void Show();
}

class ConfigurationView : IConfigurationView
{
    Form form;
    Button selectConfigurationFileButton;
    Label fullPathLabel;

    public event EventHandler SelectConfigurationFile;

    public ConfigurationView()
    {
        // UI initialization.

        this.selectConfigurationFileButton.Click += delegate
        {
            var Handler = this.SelectConfigurationFile;

            if (Handler != null)
            {
                Handler(this, EventArgs.Empty);
            }
        };
    }

    public void SetConfigurationFile(string fullPath)
    {
        this.fullPathLabel.Text = fullPath;
    }

    public void Show()
    {
        this.form.ShowDialog();        
    }
}

interface IConfigurationPresenter
{
    void ShowView();
}

class ConfigurationPresenter : IConfigurationPresenter
{
    Configuration configuration = new Configuration();
    IConfigurationView view;

    public ConfigurationPresenter(IConfigurationView view)
    {
        this.view = view;            
        this.view.SelectConfigurationFile += delegate
        {
            // The ISelectFilePresenter and ISelectFileView behaviors
            // are implicit here, but in a WinForms case, a call to
            // OpenFileDialog wouldn't be too far fetched...
            var selectFilePresenter = Gimme.The<ISelectFilePresenter>();
            selectFilePresenter.ShowView();
            this.configuration.FullPath = selectFilePresenter.FullPath;
            this.view.SetConfigurationFile(this.configuration.FullPath);
        };
    }

    public void ShowView()
    {
        this.view.SetConfigurationFile(this.configuration.FullPath);
        this.view.Show();
    }
}

в дополнение к вышесказанному, у меня обычно есть база IView интерфейс, где я спрятал Show() и любое представление владельца или название представления, которое обычно используют мои представления.

в свой вопросы:

1.когда winform загружается, он должен получить treeview. Правильно ли я думаю, что представление должно поэтому вызывать такой метод, как: presenter.gettree (), это, в свою очередь, делегирует модель, которая получит данные для treeview, создаст его и настроит, вернет его презентатору, который, в свою очередь, перейдет к представлению, которое затем просто назначит его, скажем, панели?

Я бы звоните IConfigurationView.SetTreeData(...) С IConfigurationPresenter.ShowView(), прямо перед вызовом IConfigurationView.Show()

2.будет ли это то же самое для любого элемента управления данными в Winform, так как у меня также есть datagridview?

Да, я бы назвал IConfigurationView.SetTableData(...) для этого. Это представление для форматирования данные. Ведущий просто подчиняется контракту представления, что ему нужны табличные данные.

3.мое приложение, имеет номер классов моделей с одной и той же сборкой. Он также поддерживает архитектуру плагинов с плагинами, которые должны быть загружены при запуске. Будет ли представление просто вызывать метод presenter, который, в свою очередь, вызовет метод, который загружает плагины и отображает информацию в представлении? Какой уровень будет затем управлять ссылками плагина. Бы просмотреть ссылки на них или ведущий?

если Плагины связаны с представлением, то представления должны знать о них, но не ведущий. Если они все о данных и модели, то представление не должно иметь ничего общего с ними.

4.правильно ли я думаю, что представление должно обрабатывать каждую вещь о представлении, от цвета узла treeview, до размера datagrid и т. д.?

да. Подумайте об этом как о презентаторе, предоставляющем XML, который описывает данные и представление, которое принимает данные и применяет к ним таблицу стилей CSS. В конкретные условия, ведущий может назвать IRoadMapView.SetRoadCondition(RoadCondition.Slippery) и вид затем отображает дорогу в красном цвете.

а как насчет данных, для нажата узлов?

5.если я нажимаю на treenodes, должен ли я пройти через определенный узел к презентатору, а затем из этого презентатора будет работать, какие данные ему нужны, а затем запрашивает модель для этих данных, прежде чем представить ее обратно в представление?

если возможно, я бы передал все данные, необходимые для представления дерева в виде в одном кадре. Но если некоторые данные слишком велики для передачи с самого начала или если они динамичны по своей природе и нуждаются в "последнем снимке" из модели (через презентатора), то я бы добавил что-то вроде event LoadNodeDetailsEventHandler LoadNodeDetails в интерфейс просмотра, чтобы ведущий мог подписаться на него, извлеките сведения об узле в LoadNodeDetailsEventArgs.Node (возможно, через какой-то идентификатор) из модели, так что вид может обновить его показано сведения об узле при возврате делегата обработчика событий. Обратите внимание, что асинхронные шаблоны этого могут потребоваться, если извлечение данных может быть слишком медленным для хорошего пользовательского опыта.

ведущий, который содержит все логика в представлении, должны реагировать на кнопку нажата как @JochemKempe говорит. С практической точки зрения, кнопка событие click обработчик вызовов presenter.OpenFile(). Ведущий может определить, что должно быть сделано.

если он решит, что пользователь должен выбрать файл перезванивает в вид (через интерфейс представления) и пусть представление, которое содержит все технические характеристики пользовательского интерфейса, отображает OpenFileDialog. Это очень важное различие в том, что презентатору не должно быть разрешено выполнять операции, связанные с используемой технологией пользовательского интерфейса.

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

основная причина использования шаблона MVP, imo заключается в том, чтобы отделить технологию пользовательского интерфейса от логики представления. Таким образом, ведущий организует всю логику во время просмотра сохраняет его отдельно от логики пользовательского интерфейса. Это имеет очень хороший побочный эффект, что делает презентер полностью тестируемым модулем.

обновление: так как ведущий является воплощением логики, найденной в один конкретный вид, отношение представления-презентатора является ИМО отношением один-к-одному. И для всех практических целей один экземпляр представления (скажем, форма) взаимодействует с одним экземпляром презентатора, а один экземпляр презентатора взаимодействует только с одним представлением пример.

тем не менее, в моей реализации MVP с WinForms ведущий всегда взаимодействует с представлением через интерфейс, представляющий возможности пользовательского интерфейса представления. Нет никаких ограничений на то, какое представление реализует этот интерфейс, поэтому разные "виджеты" могут реализовать один и тот же интерфейс представления и повторно использовать класс presenter.

ведущий должен действовать на конце запроса показать окно openfiledialog, как вы предложили. Поскольку от модели не требуется никаких данных, докладчик может и должен обрабатывать запрос.

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

Comments

    Ничего не найдено.