views:

44

answers:

2

For example, this list contains an overview of documents and needs to allow paging. The list is used throughout the website.

Depending on the context where it is used, it needs the data from a different source. For example, it can be used on a 'group' page, where it needs to load the documents for the group. And it can be used on an 'event' page, where it needs to load the documents for the event.

Both situations can also have different filtering on the documents withing the page.

Should the list not have different datasources, I could easily use Html.RenderAction, and start working from there.

But do I supply the list with documents in the caller, or should the list load the documents, depending on filter/paging/... viewdata?

A: 

You could implement the list as a partial view instead of a controller action. Then you can use RenderPartial to render the list and pass in a different list of objects depending on what the list should display.

If you pass in an IEnumerable as a model for example you can implement paging using something like Model.Skip(page * pagesize).Take(pagesize)

updated

Let's not do paging in the view. It might be a better idea to create a model class that does the paging and is actually testable and pass that into the view to serve up the right page of documents. Of course the view is still responsible for showing pages and linking to other pages.

You could create something like a DocumentPager class that wraps an IEnumerable and that does paging. This would look something like this

public class DocumentPager {
    public IEnumerable<MyDocumentObject> DocSource { get; private set; }
    public int PageSize { get; private set; }

    public DocumentPager(IEnumerable<MyDocumentObject> docSource, int pageSize) {
        DocSource = docSource;
        PageSize = pageSize;
    }

    public IEnumerable<MyDocumentObject> GetPage(int pageNumber) {
        return DocSource.Skip(..etc).Take(..etc);
    }

    public int NumPages {
        get { return DocSource.Count() / PageSize; }
    }
}

You can then pass this into the view and into your partial view that can call the GetPage and NumPages method and property.

Mendelt
Interesting, but when executing Take(), then the underlying repository is called and then the SQL is executed (could work, I'm using Linq to NHIbernate). But isn't it a what strange approach to use the Skip() and Take() in the frontend?
Bertvan
Ah, you found a weak spot in my answer. And you're completely right of course. Paging isn't view-logic and shouldn't be in the view. I think the basic approach of using a partial view that can render different data instead of Html.RenderAction is still valid but maybe we can push the paging-logic into a view-class.
Mendelt
Ok, at this point I started doing a similar approach as the one you mention in your answer (DocumentPager). With that difference that is is responsible for loading the documents through the repository iso through an IEnumerable.Next question though: what about the 'Next' and 'Previous' link? :)
Bertvan
Will edit your answer with a nice link, doing something similar: http://xlib.wordpress.com/2009/07/25/asp-net-mvc-grid-%E2%80%93-part-7-%E2%80%93-reusable-control/
Bertvan
A: 

Maybe you can do something with ScottGu's PagedList class which can be found here: http://blog.wekeroad.com/2007/12/10/aspnet-mvc-pagedlistt/

Kristof Claes
This paged list is one thing (I have a similar implementation of it at this point), but it does not provide the whole solution of having a reusable frontend component.
Bertvan