views:

33

answers:

1

Background:
I'm trying to implement a tab control. The tabs are as follows:

| Funds | Companies | Groups |

and are implemented as follows:

<ul class="ActionControl">

    <li>
        <%=Html.ActionLink(string.Format("Funds ({0})", Model.Summary.FundCount)
            , "ResultsList", new {selectedTab = "Funds"} ) %>
    </li>
    // more tabs removed for brevity, one <li> for each
</ul>

Each tab is a link to an action method, which is defined as:

public PartialViewResult ResultsList(SearchViewModel search)
{
    var result = new SearchViewModel
    {

        Summary = _entitySearchService.GetSearchDataSummary(search.SearchExpression),
        PagedFunds = _fundService.GetPagedEntitiesByName<Fund>(10, search.SearchExpression),
        PagedCompanies = _companyService.GetPagedEntitiesByName<Company>(10, search.SearchExpression),
        PagedGroups = _groupService.GetPagedEntitiesByName<CompanyGroupInfo>(10, search.SearchExpression)
    };
}

This works, but it's not correct, because I only want to bring back data for the tab that's clicked. It's possible for me to do a switch() on the value stored in search.SelectedTab and populate only the property that's associated with the clicked tab, but this is messy.

Also, this presents a problem in the Partial View, becuase I have to differentiate between the tabs to identify which one I should populate the table with. Currently this is how I'd populate the results panel if you clicked the Funds tab:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SearchViewModel>" %>

<% Html.RenderPartial("Tabs"); %>

<table>

    <% foreach (var item in Model.PagedFunds) {%>

        <tr>
            <td><%= item.Name %></td>
        </tr>

    <% }%>

</table>

For reference, this is SearchViewModel:

public class SearchViewModel
{
    public string SearchExpression { get; set; }
    public string SelectedTab { get; set; }

    public SearchDataSummary Summary { get; set; }

    public Paging<Fund> PagedFunds { get; set; }
    public Paging<Company> PagedCompanies { get; set; }
    public Paging<CompanyGroupInfo> PagedGroups { get; set; }
}

and the signature for Paging is:

public class Paging<T> : List<T> // contains functionality to manage paging and act like a List<T>

Question:
What's the best way for me to approach this issue?

Should I have separate action methods for each tab? So clicking Funds goes to

public PartialViewResult Funds(SearchViewModel search)

and returns ViewUserControl<Paging<Fund>>

and clicking Companies goes to

public PartialViewResult Companies(SearchViewModel search)

and returns ViewUserControl<Paging<Company>>

Ideally I could keep the single ResultsView action method and have a more generic approach to returning the paged items. I think this is possible but I'm getting too bogged down in the details and I'm not able to see the wood for the trees. Could somebody please point out an approach I could take? Thanks

A: 

When we implemented tabs (JQuery UI) in one of our MVC sites, we went with the separate action methods for each tab. In our case, the tabs were different enough that we had to have separate partialViews for each tab anyways.

Even if you can use the same partialView, I think you will have much less headache and maintenance by using distinct methods for each tab (think readability, issue tracing, future enhancements). Keeping the one action, think of the what if's....What if companies needs its own partial view, what if funds needs some different search criteria, what if we have to add more tabs? Sure, you can solve all of these in the current setup, but at what point does it become un-maintainable. Being able to solve all of these and more will be better with the distinct action methods IMHO.

Tommy
I decided to go with your suggestion.. at least for now. If I can see a path to doing it generically again, I'll see what I can do. But for now, I have to make progress and your suggestion works. Thanks
DaveDev