これは、MVPデザインパターンを使用したパッシブビューの概念を示す簡単な例です。パッシブビューを使用しているため、ビューにはプレゼンターの知識がありません。プレゼンターは、ビューによって公開されたイベントをサブスクライブし、それに応じて行動します。
まず、ビューのコントラクトを定義する必要があります。これは通常、インターフェースを使用して実現されます。基本的に、ビューとの結合を非常に緩くしたいと考えています。ユニットテスト用に、別のビューに切り替えたり、イベント作成のモックビューを作成したりできるようにする必要があります。
これは、顧客情報を表示するために使用される単純なビューを説明する契約です。
public interface ICustomerManagementView
{
void InitializeCustomers(ICustomer[] customers);
void DisplayCustomer(ICustomer customer);
event EventHandler<EventArgs<ICustomer>> SelectedCustomerChanged;
}
モデルのオブジェクトでビューを初期化するために使用される単一のメソッドInitializeCustomersを公開します。
ビューでアクションが発生したという通知を受け取るためにプレゼンターが使用するイベントSelectedCustomerChangedもあります。
契約を結ぶと、プレゼンターでこれらのやり取りの処理を開始できます。
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);
}
}
}
プレゼンターでは、依存性注入と呼ばれる別のデザインパターンを使用して、ビューと必要なモデルクラスへのアクセスを提供できます。この例では、顧客の詳細を取得する責任があるCustomerRepositoryがあります。
コンストラクターには、2つの重要なコード行があります。最初に、ビューのSelectedCustomerChangedイベントをサブスクライブしました。ここで、関連するアクションを実行できます。次に、リポジトリからのデータを使用してInitilaizeCustomersを呼び出しました。
この時点では、ビューの具体的な実装を実際に定義していません。必要なのは、ICustomerManagementViewを実装するオブジェクトを作成することだけです。たとえば、Windowsフォームアプリケーションでは、次のことができます。
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;
}
プレゼンテーションロジックをテストしたい場合は、ビューをモックしていくつかのアサーションを実行できます。
編集:含まれているカスタムイベント引数
public class EventArgs<T> : EventArgs
{
private readonly T _value;
public EventArgs(T value)
{
_value = value;
}
public T Value
{
get { return _value; }
}
}