C # WinForms Model-View-Puster (Passive View)
-
29-09-2019 - |
Вопрос
Я разрабатываю приложение WinForms в C #. У меня ограниченный опыт работы в программировании GUI, и мне нужно многозначить на лету. Это сказано, вот что я строит.
Смотрите общий GUI посмотреть на следующую ссылку:
GUI http://img227.imageshack.us/img227/1084/program0.jpg.
Теперь я уже много работал, но в самом плохом автономном дизайне. Я не знал, что проект когда-либо достигнет определенного размера, и, как таковой, настало время сделать какой-то крупный рефакторинг.
Я очень изучаю об узорах дизайна GUI, и шаблон, который я желаю реализовать, это пассивный вид (см. http://martinfowler.com/eaadev/passivescreen.html.). Я ищу некоторую помощь о том, как принести это все вместе.
Фон:
1) В зависимости от того, что пользователь нажимает в «TreeView», «Список» в нижнем левом углу будет отображаться список объектов, которые могут заполнить область «редактора». Эти объекты могут быть текстовым ящиком или DataGridView. Пользователь переключает список, чтобы выбрать то, что он / она хочет увидеть в «редакторе»
2) Модель по существу является папкой с файлами данных и конфигурации. Существует внешняя программа, которая работает в данном каталоге, создает выходные файлы / папки и т. Д. Эта программа, которую я разработан, предназначена для эффективного управления / настраивания этих объектов в удобном уровне
3) Проблема с тем, как я делаю вещи, так это то, что она находится рядом с невозможным тестирование, и, следовательно, переход к Passive Passive Passive View Passive View MVP-ESQU.
Я пытаюсь сделать это так, чтобы программа работать независимо от вида. Я не смог найти какие-либо примеры, где более сложный, интерактивный вид используется с пассивным рисунком вида.
Вопросы:
1) Нужно ли реализовать один большой интерфейс / представление для всего «внешнего вида» программы, затем внедряет подменные интерфейсы / подсвидетельства для каждого из дерева, редактора, регистратора и т. Д.? Или есть лучшая «структура» для этого?
2) Когда дело доходит до «сдача» событий с точки зрения докладчика / контроллера (какая бы ни была терминология, которую вы хотите использовать, WRT Passive View Pattern Design), как я должен делать это? Иногда у меня есть простые свойства, которые необходимо обновлять, а иногда мне нужна целая серия шагов, чтобы развернуться.
Я бы полюбил предложения и советы по этой теме. Я расчерил Интернет, и я не нашел адекватных примеров, чтобы помочь мне продолжить с этим проектом.
Заранее спасибо!
Даниэль
Решение
Вот простой пример, который демонстрирует концепцию пассивных взглядов с использованием шаблона дизайна MVP. Поскольку мы используем пассивные взгляды, вид не имеет знания о ведущем. Ведущий будет просто подписаться на события, опубликованные по мнению и действуют соответствующим образом.
Чтобы начать нам нужно определить договор на наш взгляд. Обычно это достигается с использованием интерфейса, по существу, мы хотим иметь очень свободную муфту с нашим видом. Мы хотим возможность переключаться на разные представления или событие создавать представления издевательства для тестирования подразделения.
Вот договор, который описывает простой вид, который будет использоваться для отображения информации о клиенте
public interface ICustomerManagementView
{
void InitializeCustomers(ICustomer[] customers);
void DisplayCustomer(ICustomer customer);
event EventHandler<EventArgs<ICustomer>> SelectedCustomerChanged;
}
Он обнародует один метод Инициализированные элементы Это будет использоваться для инициализации нашего представления с объектами из нашей модели.
У нас также есть событие ВыбратьCustomerChanged Это будет использоваться нашим ведущим для получения уведомления о том, что действие произошло в поле зрения.
Как только у нас будет наш контракт, мы можем начать обрабатывать эти взаимодействия в нашем докладчике.
public class CustomerManagementPresenter
{
private ICustomer _selectedCustomer;
private readonly ICustomerManagementView _managementView;
private readonly ICustomerRepository _customerRepository;
public CustomerManagementPresenter(ICustomerManagementView managementView, ICustomerRepository customerRepository)
{
_managementView = managementView;
_managementView.SelectedCustomerChanged += this.SelectedCustomerChanged;
_customerRepository = customerRepository;
_managementView.InitializeCustomers(_customerRepository.FetchCustomers());
}
private void SelectedCustomerChanged(object sender, EventArgs<ICustomer> args)
{
// Perform some logic here to update the view
if(_selectedCustomer != args.Value)
{
_selectedCustomer = args.Value;
_managementView.DisplayCustomer(_selectedCustomer);
}
}
}
В докладчике мы можем использовать другой рисунок дизайна внедрение зависимости Обеспечить доступ к нашему мнению и любые модели моделей, которые нам могут понадобиться. В этом примере у меня есть кабинет, который отвечает за получение деталей клиентов.
В конструкторе у нас есть две важные строки кода, во-первых, мы подписались на событие «ВыбранныеCUSTOMERChanged» на наш взгляд, именно здесь мы можем выполнять связанные действия. Во-вторых, мы назвали interilaizecustomers с данными из репозитория.
На этом этапе мы на самом деле не определили конкретное реализацию для нашего представления, все, что нам нужно сделать, это создать объект, который реализует Icustomermanagementview.. Отказ Например, в приложении Windows Forms мы можем сделать следующее
public partial class CustomerManagementView : Form, ICustomerManagementView
{
public CustomerManagementView()
{
this.InitializeComponents();
}
public void InitializeCustomers(ICustomer[] customers)
{
// Populate the tree view with customer details
}
public void DisplayCustomer(ICustomer customer)
{
// Display the customer...
}
// Event handler that responds to node selection
private void CustomerTreeViewAfterSelect(object sender, TreeViewEventArgs e)
{
var customer = e.Node.Tag as ICustomer;
if(customer != null)
{
this.OnSelectedCustomerChanged(new EventArgs<ICustomer>(customer));
}
}
// Protected method so that we can raise our event
protected virtual void OnSelectedCustomerChanged(EventArgs<ICustomer> args)
{
var eventHandler = this.SelectedCustomerChanged;
if(eventHandler != null)
{
eventHandler.Invoke(this, args);
}
}
// Our view will raise an event each time the selected customer changes
public event EventHandler<EventArgs<ICustomer>> SelectedCustomerChanged;
}
Если бы мы хотели проверить нашу логику презентации, мы могли бы издеваться над нашим взглядом и выполнять некоторые утверждения.
Редактировать: включенные пользовательские события ARGS
public class EventArgs<T> : EventArgs
{
private readonly T _value;
public EventArgs(T value)
{
_value = value;
}
public T Value
{
get { return _value; }
}
}
Другие советы
Я бы сломал их на отдельных взглядах со своими собственными подарками и использовать «контроль» докладчика / представления для управления делегированием сообщений между ними. Не только это будет реализобновить эту помощь, но она будет держать ваши контрольные средства, выполняющие SRP тоже.
Таким образом, в вашем случае у вас может быть IFOMMMANAGER, который будет реализовать ваше главное окно, а затем IFILEMANGER, ILOGGERWINDOW и т. Д. И т. Д.
Хотя это может быть немного излишним для использования, я бы предположил, что вы посмотрите на программное обеспечение Smart Client Software (из команды Microsoft Photers и Transeics) - это не активно развивается, но он имеет хорошую реализацию MVP и Этот вид просмотра состав довольно хорошо, поэтому может дать вам несколько хороших идей.