tags:

views:

272

answers:

3

I am new to the whole MVP thing and slowly getting my head around it all. The a problem I am having is how to stay consistent with the MVP methodology when populating GridViews (and ddls, but we will tackle that later).

Is it okay to have it connected straight to an ObjectDataSourceID? To me this seems wrong because it bypasses all the separation of concerns MVP was made to do.

So, with that said, how do I do it? How do I handle sorting (do I send over handler events to the presentation layer, if so how does that look in code)? Right now I have a GridView that has no sorting. Code below.

ListCustomers.aspx.cs:

public partial class ListCustomers : System.Web.UI.Page, IlistCustomer
{
protected void Page_Load(object sender, EventArgs e)
{
    //On every page load, create a new presenter object with
    //constructor  recieving the 

    //  page's IlistCustomer view 
    ListUserPresenter ListUser_P = new ListUserPresenter(this);

    //Call the presenter's PopulateList to bind data to gridview
    ListUser_P.PopulateList();

}

GridView IlistCustomer.UserGridView
{
    get { return gvUsers; }
    set { gvUsers = value; }
}

}

Interface ( IlistCustomer.cs): is this bad sending in an entire Gridview control?

public interface IlistCustomer
{
GridView UserGridView { set; get; }
}

The Presenter (ListUserPresenter.cs):

public class ListUserPresenter
{
private IlistCustomer view_listCustomer;
private GridView gvListCustomers;
private DataTable objDT;

public ListUserPresenter( IlistCustomer view)
{
    //Handle an error if an Ilistcustomer was not sent in)
    if (view == null)
        throw new ArgumentNullException("ListCustomer View cannot be blank");

    //Set local IlistCustomer interface view
    this.view_listCustomer = view;
}

public void PopulateList()
{
    //Fill local Gridview with local IlistCustomer
    gvListCustomers = view_listCustomer.UserGridView;

    // Instantiate a new CustomerBusiness object to contact database
    CustomerBusiness CustomerBiz = new CustomerBusiness();

    //Call CustomerBusiness's GetListCustomers to fill DataTable object
    objDT = CustomerBiz.GetListCustomers();

    //Bind DataTable to gridview;
    gvListCustomers.DataSource = objDT;
    gvListCustomers.DataBind();
}
}
A: 

The convenience of using a database aware control, like Gridview, is a huge temptation. In theory one could just roll their own gridview and remain true to the MVP design. But you will be duplicating work and giving the finite resources of businesses not often the wisest choice. Since the time saving can be considerable there are compelling reason to use database aware controls.

The compromise is to clearly document via code the path in which the control connects to the database. That way if and when you migrate the UI, backend or both, you can see what is dependent on the database aware control and the backend. Also look over the database apis offered by your framework. You may have a close to generic choice that minimize problem with changing backends.

When planning your design the key question to ask is "What happens if I change the UI, the presenter, the view, the model, or database backend. The answer hopefully will lead you to a design that allows for changes.

RS Conley
Ah, So probably don't want to use gridviews huh? I am going to do some more research on the best way to do this in the design I am looking for. Thanks for giving me a new path to research.
DotNetDan
Sure, but remember the gridview can be a tremendous timesaver so factor that in as well. As long as is the connection between the database to the gridview is clearly document you should be alright for future releases.
RS Conley
A: 

The view interface should not expose UI components; my take would be the following

public interface IlistCustomer
{
   PopulateCustomers(IEnumerable<Customer> customers);
}

public class ListUserPresenter
{
private IlistCustomer _view;

public ListUserPresenter(IlistCustomer view)
{
    //Handle an error if an Ilistcustomer was not sent in)
    if (view == null)
        throw new ArgumentNullException("view");    

    _view = view;
}

public void PopulateList()
{
   //Injecting your DAL seems like a good choice here
    CustomerBusiness CustomerBiz = new CustomerBusiness();    

    IEnumerable<Customer> customers = CustomerBiz.GetListCustomers();

    _view.PopulateCustomers(customers);
}
}
Leyu
You are very correct Leyu. I realized it was wrong when I was doing it, but I couldn't find any other way at the time being a full web forms guy. What I thought I knew about what should be in the view was wrong. I thought it shouldn't do anything other than give items to be filled by the presenter. Now I understand that the view should do more than I thought.Thanks Leyu for your input. It was helpful.
DotNetDan
A: 

I will start by highlighting the main concerns addressed by the MVP as pattern. Firstly it is to achieve modularity through separation of concerns. This means that one can ideally change the View layer from say Web Forms to Windows forms without chnaging anything in the Presenter and Model layers. Secondly, an application designed using MVP lends itself easily to unit testing since it is very difficult to test a form. With this in mind then you realize that View-centric objects like Grid should not be manipulated in the Presenter layer since when the View changes, the controls are also likely to change. To answer your question I can approach your problem in the following manner:

// View
public interface IListCustomersView
{
    public void BindGrid(IList<Customer> customers);
}

// Form e.g. Web Form, Windows Form
public class ListCustomers : IListCustomersView
{
    private ListCustomersPresenter listCustomerPresenter = null;

    public ListCustomers()
    {
        // You can use a Dependency Injector here
        this.listCustomersPresenter = new ListCustomerPresenter(
            new CustomerRepository(),
            this);
    }

    public void BindGrid(IList<Customer> customers)
    {
            grid.DataSource = customers;
            grid.Databind();
    }
}

// Presenter
public class ListCustomersPresenter
{
    private readonly IListCustomersView view = null;
    private readonly ICustomerRespository repository = null;

    public ListCustomersPresenter(
         ICustomerRespository  customerRepository, IListCustomersView view)
    {
        Guard.AgainstNull(view,"View");
        Guard.AgainstNull(customerRepository,"CustomerRepository");

        this.view = view;
        this.customerRepository = customerRepository;
    }

    public void BindGrid()
    {
         // Fetch customers from repository
         IList<Customer> customers = this.customerRepository.GetCustomers();
         view.BindGrid(customers);          
    }
}
Waliaula Makokha