Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Here is a simple example that demonstrates the concept of passive views using the MVP design pattern. Because we are using passive views the view has no knowledge of the presenter. The presenter will simply subscribe to events published by the view and act accordingly.</p> <p>To start out we need to define a contract for our view. This is typically achieved using an interface, essentially, we want to have a very loose coupling with our view. We want the ability to switch to different views or event create mock views for unit testing.</p> <p>Here is a contract that describes a simple view that will be used to display customer information</p> <pre><code>public interface ICustomerManagementView { void InitializeCustomers(ICustomer[] customers); void DisplayCustomer(ICustomer customer); event EventHandler&lt;EventArgs&lt;ICustomer&gt;&gt; SelectedCustomerChanged; } </code></pre> <p>It exposes a single method <b>InitializeCustomers</b> that will be used to initialize our view with objects from our model.</p> <p>We also have an event <b>SelectedCustomerChanged</b> that will be used by our presenter to receive notification that an action has occurred in the view.</p> <p>Once we have our contract we can start to handle these interactions in our presenter.</p> <pre><code>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&lt;ICustomer&gt; args) { // Perform some logic here to update the view if(_selectedCustomer != args.Value) { _selectedCustomer = args.Value; _managementView.DisplayCustomer(_selectedCustomer); } } } </code></pre> <p>In the presenter we can use another design pattern called <a href="http://en.wikipedia.org/wiki/Dependency_injection" rel="noreferrer">dependency injection</a> to provide access to our view and any model classes that we may need. In this example I have a CustomerRepository that is responsible for fetching customer details.</p> <p>In the constructor we have two important lines of code, firstly we have subscribed to the SelectedCustomerChanged event in our view, it is here that we can perform associated actions. Secondly we have called InitilaizeCustomers with data from the repository.</p> <p>At this point we haven't actually defined a concrete implementation for our view, all we need to do is create an object that implements <b>ICustomerManagementView</b>. For example in a Windows Forms application we can do the following</p> <pre><code>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&lt;ICustomer&gt;(customer)); } } // Protected method so that we can raise our event protected virtual void OnSelectedCustomerChanged(EventArgs&lt;ICustomer&gt; 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&lt;EventArgs&lt;ICustomer&gt;&gt; SelectedCustomerChanged; } </code></pre> <p>If we wanted to test our presentation logic we could mock our view and perform some assertions.</p> <p>EDIT : Included custom event args</p> <pre><code>public class EventArgs&lt;T&gt; : EventArgs { private readonly T _value; public EventArgs(T value) { _value = value; } public T Value { get { return _value; } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload