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