Nei tre post precedenti ho tralasciato la gestione del click sui pulsanti OK e Cancel; ripensandoci mi sono reso conto che la loro implementazione introduce alcune soluzioni nell'architettura dell'applicazione che per chi non è avvezzo ad utilizzare l'MVP possono risultare un pò ostici.
Iniziamo da quello più semplice e cioè la gestione del pulsante Cancel, in questo caso la form deve semplicemente chiudere ed impostare la property DialogResult al valore DialogResult.Cancel.
La view quando viene premuto il button Cancel segnala l'evento OnCancel al quale il presenter deve essere sottoscritto, quindi nel metodo SetUp della classe SelectSymbolPresenterTests aggiungiamo il codice per verificare che il presenter si sottoscriva all'evento:
_view.OnCancel += null;
_onCancelRaiser = LastCall.Repeat.Once().IgnoreArguments().GetEventRaiser();
Procediamo nella scrittura del codice del test:
[Test]
public void WhenTheViewRaisesTheOnCancelEventThePresenterCallsTheCloseMetod()
{
_view.Close(false);
LastCall.Repeat.Once();
_mocks.ReplayAll();
new SelectSymbolPresenter(_model, _view);
_onCancelRaiser.Raise(_view, EventArgs.Empty);
}
L'unica azione che ci aspettiamo faccia il presenter è di chiamare il metodo Close della view passando al parametro confirm il valore false. Anzichè il parametro boolean confirm avremmo potuto esporre direttamente la property DialogResult della view in modo da renderne più semplice l'implementazione, ma in questo caso dipenderemmo dalle windows forms ed il codice sarebbe meno portabile.
Per complare il codice del test dobbiamo aggiungere l'evento OnCancel e il metodo Close all'interfaccia ISelectSymbolView:
public interface ISelectSymbolView
{
event EventHandler SelectedChartPaneChanged;
event EventHandler OnCancel;
void FillSymbolNameList(string[] symbolNames);
void FillChartPaneList(string[] chartPaneNames);
void SelectPlotInPaneOption();
void Close(bool confirm);
}
L'implementazione nella form sarà:
public void Close(bool confirm)
{
if (confirm)
{
this.DialogResult = DialogResult.OK;
}
else
{
this.DialogResult = DialogResult.Cancel;
}
}
private void CancelButton_Click(object sender, EventArgs e)
{
if (OnCancel != null)
{
OnCancel(this, EventArgs.Empty);
}
}
Per evitare l'if nella view avremmo potuto esporre due metodi di close uno con conferma e l'altro senza conferma, ma è più questione di gusti che altro.
Ora non rimane che completare il presenter per fare passare il test, nel costruttore ci sottoscriviamo all'evento OnCancel:
_view.OnCancel += new EventHandler(View_OnCancel);
Ed infine scriviamo il metodo View_OnCancel
void View_OnCancel(object sender, EventArgs e)
{
_view.Close(false);
}
Per riepilogare vediamo l'interazione tra la view e il presenter tramite un sequence diagram:
Come si può vedere non è stato coinvolto il model in quanto non abbiamo agito su oggetti di business.
La parte più interessante è la gestione del click sul pulsante ok.
Continua...