Это мой скромный взгляд на MVP и ваши конкретные проблемы.
Во-первых , все, с чем пользователь может взаимодействовать или просто показывать, является представлением . Законы, поведение и характеристики такого вида описываются интерфейсом . Этот интерфейс может быть реализован с использованием пользовательского интерфейса 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()
{
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
{
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, поскольку у меня также есть datagridview?
Да, я бы позвонил IConfigurationView.SetTableData(...)
по этому поводу. Форматирование предоставленных ему данных зависит от представления. Ведущий просто подчиняется контракту представления о том, что ему нужны табличные данные.
3. Мое приложение содержит несколько классов моделей с одной и той же сборкой. Он также поддерживает архитектуру плагинов с плагинами, которые необходимо загружать при запуске. Будет ли представление просто вызывать метод докладчика, который, в свою очередь, вызывает метод, который загружает плагины и отображает информацию в представлении? Какой уровень затем будет управлять ссылками на подключаемые модули. Будет ли представление содержать ссылки на них или на докладчика?
Если плагины связаны с представлениями, то о них должны знать представления, но не докладчик. Если все они касаются данных и модели, то представление не должно иметь к ним никакого отношения.
4. Правильно ли я считаю, что представление должно обрабатывать все, что касается представления, от цвета узла древовидного представления до размера сетки данных и т. Д.?
Да. Думайте об этом как о докладчике, предоставляющем XML, который описывает данные, и представление, которое принимает данные и применяет к ним таблицу стилей CSS. Говоря конкретнее, докладчик может позвонить, IRoadMapView.SetRoadCondition(RoadCondition.Slippery)
и представление затем отобразит дорогу красным цветом.
А как насчет данных для узлов, по которым щелкнули?
5. Если, когда я щелкаю по тринодам, должен ли я пройти через конкретный узел к ведущему, а затем, исходя из этого, ведущий определит, какие данные ему нужны, а затем запросит эти данные у модели, прежде чем представить их обратно в представление?
Если возможно, я бы передал все данные, необходимые для представления дерева в виде за один раз. Но если некоторые данные слишком велики для передачи с самого начала или если они динамичны по своей природе и нуждаются в «последнем снимке» из модели (через презентатора), то я бы добавил что-то вроде event LoadNodeDetailsEventHandler LoadNodeDetails
интерфейса просмотра, чтобы презентатор может подписаться на него, получить сведения об узле LoadNodeDetailsEventArgs.Node
(возможно, через его какой-либо идентификатор) из модели, чтобы представление могло обновлять отображаемые сведения об узле при возвращении делегата обработчика событий. Обратите внимание, что для этого могут потребоваться асинхронные шаблоны, если выборка данных может быть слишком медленной для хорошего взаимодействия с пользователем.