it-swarm.com.ru

Модель-Представление-Презентатор в WinForms

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

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

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

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

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

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

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

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

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

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

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

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

86
Darren Young

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

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

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

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

Последствия третьего:

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

Для вашей проблемы, приведенное выше может выглядеть следующим образом в несколько упрощенном коде:

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 загружается, она должна получить древовидную структуру. Правильно ли я считаю, что представление должно вызывать такой метод, как: Presenter.gettree (), это, в свою очередь, делегирует модели, которая получит данные для древовидного представления, создаст и настроит их, вернет их докладчик, который, в свою очередь, перейдет к представлению, которое затем просто назначит его, скажем, панели?

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

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

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

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

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

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

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

А как насчет данных для выбранных узлов?

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

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

118
Johann Gerell

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

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

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

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

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

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

10
Peter Lillevold

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

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

2
JochemKempe