I don't think it is a wise idea to have View and Presenter being coupled so tight.
Based on either the Passive Screen
or Supervising Presenter the presenter and the view are separated by an interface that is implemented by the view. The presenter calls the interface. Here is an example of a supervising presenter.
PRESENTER
this class has no dependency on the used GUI library
public class Presenter
{
IView view;
public Presenter(IView view)
{
this.view = view;
}
public void ValidateInPut(string value)
{
if (!String.IsEmptyOrNull(value) && value.Contains("9"))
{
view.ShowError("The value in the Text box is invalid");
}
}
}
ViewInterface
public inteface IView
{
void ShowError(string message);
}
VIEW
public class Form1:Form, IView
{
private Presenter presenter;
public Form1()
{
this.presenter = new Presenter(this); // or have a Dependcy Injection Framework do this
}
private void txtACNo_Validating(object sender, CancelEventArgs e)
{
presenter.ValidateInPut(txtACNo); // validate
}
public void IView.ShowError(string message);
{
MessageBox.Show(mesage);
}
}
Rationale
By utilizing your view and presenter the presenter (with all its (busines)logic) becomes easily testable or the view can be replaced by a WebPage without the need to adapt your presenter logic.
Test
public class Test:IView
{
bool showErrorCalled = false;
public void Test()
{
var p = new Presenter(this);
showErrorCalled = false;
p.ValidateInput("8");
Test.Assert(showErrrocalled);
}
public void IView.ShowError(string message);
{
showErrorCalled = true;
}
}
WebPage
public Default:Page, IView
{
private Presenter presenter;
public Default()
{
this.presenter = new Presenter(this);
}
public Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
presenter.ValidateInput(txtAcNo.Text);
}
}
public void IView.ShowError(string message);
{
Error.Text = message;
}
}
PS
Remember that the cast operator on an object may fail. Your code
var controller = (TextBox)sender;
will only work as long as sender
is a TextBox
. It is better to check if there is a more generalized type up the hierarchy that still provides you with the needed interface. In your case that could be Control
that has a Text
property as well. A more defensive approach would be:
var controller = sender as Control; // try to cast, if not return null
if (controller != null)
{
// do stuff with controller
}
else
{
// logging
Debug.WriteLine("controller is null");
}