views:

84

answers:

3

In a three-tier model (presentation-business-data access layers), I can consistently keep my lower layers agnostic of the upper layers. For example my data access layer never knows how it is presented or what busines rules are operated on it. My business rules are agnostic of how they're presented.

But I must pray to Demeter for forgiveness or at least ask fellow Stackoverflow members for advice on one thing: How do you present a "Table" to the user without referencing the Data Access object in the Presentation Layer? Time and again, I find myself referencing a ADO.NET DataTable in a GridView object. Currently I'm using third-party tools in both layers. The Table is from OpenLink's OpenComponents Table object; the grid is an Infragistics UltraGrid (Windows platform). Yet I'm guilty of the same infraction.

edit: I am most especially interested in how this may be done with WinForm 3.5 .NET. Note my comments below: I believe the link in the comment is what I should have done, but I was hoping that I wouldn't have to get too fancy with domain objects. I don't want to be accused of over-designing. Is this a good balance?

A: 

I'm not sure how other stackoverflow members would do it, but WPF, ASP MVC, Silverlight, what you would do is use the MVVM design pattern. I'm afraid I don't have any good links for you at the moment.

In MVVM, the key idea is that your View accesses data in the ViewModel. The ViewModel presents data to the View by exposing properties. In WPF and Silverlight, you use binding to access the data and use data templates to express the exact details of how to express it. Usually you will expose a collection with an ObservableCollection. In ASP MVC, you would context switch and access the model that way.

<body> <h1><% Model.MyHeaderMessage %></h1>

I would say that what you should do is in your ViewModel (similar to a controller) hit the server / service for data, and return the recordset. Repackage the data in simple data classes, and put them in a ObservableCollection expose this to the view via a property that returns ObservableCollection. If you are doing ASP MVC, expose the data via a property that returns an IEnumerable.

MedicineMan
+1  A: 

Instead of using a datatype that represents a table, I'd use a Data Transfer Object. This would be an object that represents the logical structure of the data. It would contain nothing but data.

In this case, I'd define a DTO for my "data row" type, and then use a List<RowDTO> as the type I'd pass to the grid.

John Saunders
I was surprised just how easy this is. The grid shows columns for every public property automatically, without having to add attributes. With just a little complexity added, I now have a usefull SoC I can work with.
Blanthor
A: 

A very common pattern for this is the Model View Pattern (MVP).

The key here is to define an interface with will represent your View, for instance your view could have a property.

And a presenter that should be responsible for communacation between the view and model.

So a view would be something like these:

internal interface IListClientsView
{
    public string Title { set; }
    public IList<Client> Clients { set; }
}

And the implemantation in a web form would be this:

public partial class WebForm1 : System.Web.UI.Page, IListClientsView
{
    ListClientsPresenter presenter;
    protected void Page_Load(object sender, EventArgs e)
    {
        presenter = new ListClientsPresenter(this);
        if (!Page.IsPostBack)
            presenter.LoadView();
    }


    public IList<Client> Clients
    {
        set { GrvClients.DataSource = value;
        GrvClients.DataBind();
        }
    }
}

Of course, this could also web a winform, the key is just make the winform inplements the IxxxView interface and call the related presenter. And the presenter would look like this:

public class ListClientsPresenter
{
    IListClientsView View;
    public ListClientsPresenter(IListClientsView view)
    {
        this.View = view;
    }

    public void LoadView()
    {
        View.Title = "List of Clients";
        View.Clients = new List<Client> { 
            new Client {Name = "Client 1"},
            new Client {Name = "Client 2"}
        };
    }
}

This is a very simple example, you should check this article: http://msdn.microsoft.com/en-us/magazine/cc188690.aspx

VinTem
Originally, I was afraid to add this kind of complexity to the project. After reading more on this pattern, I may refactor to the MVP. I noticed that Boodhoo's example uses DTO's in the model.
Blanthor
I very common pattern these days is MVVM Model-View-ViewModel, wich instead of using a DTO you create a class known as ViewModel class to represent your interface. It is an option, although I prefer to use the MVP, but that's just an opinion, you should choose what's best for you. After all, there are no silver bullets ;)
VinTem