.Net Core - Putting views into a tabs

2019-06-14 05:50发布

问题:

I'm creating a web page using .Net Core and I have a pretty complex program as of now. I have two different models (Customer and User) with different properties and they each have a controller and a view.

I want to put these two views/controllers together in a tab view, so that under the Customer tab the customer index is shown and under the User tab the user index is show. I want it to be similar to what the following generates:

<div>
    <ul class="nav nav-tabs" role="tablist">
        <li role="presentation" class="active">
            <a href="#first" aria-controls="first" role="tab" data-toggle="tab">First</a>
        </li>
        <li role="presentation">
            <a href="#second" aria-controls="second" role="tab" data-toggle="tab">Second</a>
        </li>
    </ul>

    <div class="tab-content">
        <div role="tabpanel" class="tab-pane active" id="first">
            Customer
        </div>
        <div role="tabpanel" class="tab-pane" id="second">
            User
        </div>
    </div>
</div>

Is this possible in .Net Core?

EDIT1:

I am aware of how to use partial views and I was thinking this might be the way, however I am not an expert on how to use these. I just used them to restructure the way the details page for my models were shown. However as I have already implemented two complete controllers and their corresponding views I was wondering if there is an easier way?

Could I create a viewModel (containing a list of customers and users) and use that to display either? (I am using a PaginatedList on both views to order and limit the amount of items shown on the pages.). In the controller below I try to get the customers and users from the DB and pass them to the viewModel which is then passed to the View. Is this how it can be done in .Net Core? (Problem can be found in commented code in controller).

Model

public class CustomerUserViewModel
{
    public PaginatedList<Customer> Customers { get; set; }
    public PaginatedList<User> Users { get; set; }

    //OR

    public List<Customer> Customers { get; set; }
    public List<User> Users { get; set; }
}

View

@model CustomerUserViewModel

<h2>CustomerUserTabbing</h2>
<div>
    <ul class="nav nav-tabs" role="tablist">
        <li role="presentation" class="active">
            <a href="#first" aria-controls="first" role="tab" data-toggle="tab">Customer</a>
        </li>
        <li role="presentation">
            <a href="#second" aria-controls="second" role="tab" data-toggle="tab">User</a>
        </li>
    </ul>

    <div class="tab-content">
        <div role="tabpanel" class="tab-pane active" id="first">
            @Html.Partial("~/Views/Customer/Index.cshtml", Model.Customers)
        </div>
        <div role="tabpanel" class="tab-pane" id="second">
            @Html.Partial("~/Views/User/Index.cshtml", Model.Users)
        </div>
    </div>
</div>

Controller

public IActionResult CustomerUserTabbing()
{
    //I found that these two lines don't actually return anything
    //See new code below this
    //var userlist = from u in _context.Users select u;
    //var customerlist = from c in _context.Customers select c;

    //New Code
    var users = _context.Users
       .Where(u => u.UserID != 0)
       .OrderBy(u => u.First_Name)
       .ToList();
    var customers = _context.Customers
       .Where(c => c.CustomerID != 0)
       .OrderBy(c => c.Name)
       .ToList();

    CustomerUserViewModel viewModel = new CustomerUserViewModel();
    viewModel.Customers = customers; //these two lines gives errors
    viewModel.Users = users; //cannot convert IQueryable to PaginatedList

    return View(viewModel);
}

Does anyone know how to solve this?

回答1:

In earlier versions of ASP.NET MVC you can use @Html.Action(take a look at How can I use Html.Action?). It loooks similar to @Html.Partial(...) but instead of just returning an PartialView through passing a model it executes the Action (and you just have to return the PartialView after the Action processing). This way you can segregate Customer and Users responsabilities.

However, in ASP.NET Core this feature has been replace by ViewComponents https://docs.asp.net/en/latest/mvc/views/view-components.html

If you still want´s to use @Html.Action you can do it by implementing by yourself, take a look on how to do it at @Html.Action in Asp.Net Core (not the selected answer)

Regards.



回答2:

I have been using tabs for a number of years with MVC. The example provided below has 9 tabs. Each with their own Controller

@{ 
    string currentCntrlr = (string)ViewContext.RouteData.Values["controller"]; }

<nav class="container">
    <ul id="tabbedMenu">
        @if (string.IsNullOrEmpty(id)) {
            <li class="@(currentCntrlr == "Home" ? "active" : "")">@Html.ActionLink("Cover Page", "Index", "Home")</li>
        } else {
            <li class="@(currentCntrlr == "Home" ? "active" : "")">@Html.ActionLink("Cover Page", "Index2", "Home")</li>
        }
        <li class="@(currentCntrlr == "JournalIndex" ? "active" : "")">@Html.ActionLink("Index", "Index", "JournalIndex")</li>
        <li class="@(currentCntrlr == "JournalFuture" ? "active" : "")">@Html.ActionLink("Future Log", "Index", "JournalFuture")</li>
        <li class="@(currentCntrlr == "JournalMonthly" ? "active" : "")">@Html.ActionLink("Monthly Log", "Index", "JournalMonthly")</li>
        <li class="@(currentCntrlr == "JournalDaily" ? "active" : "")">@Html.ActionLink("Daily Log", "Index", "JournalDaily")</li>
        <li class="@(currentCntrlr == "JournalUser" ? "active" : "")">@Html.ActionLink("User Page", "Index", "JournalUser")</li>
        <li class="@(currentCntrlr == "JournalCalendar" ? "active" : "")">@Html.ActionLink("Calendar", "Index", "JournalCalendar")</li>
        <li class="@(currentCntrlr == "Search" ? "active" : "")">@Html.ActionLink("Search", "Index", "Search")</li>
        <li class="@(currentCntrlr == "Export" ? "active" : "")">@Html.ActionLink("Export", "Index", "Export")</li>
    </ul>
</nav>
<div class="container body-content">
    @RenderBody()
    <hr />
    <footer>
        <span class="pull-left">&copy; 2016 - LynxJournal (@ViewBag.Application)</span><span class="pull-right"><a asp-controller="Home" asp-action="Contact" title="LynxJournal Support">LynxJournal Support</a></span>
    </footer>
</div>

The active value is set in the code on the view by

@{
    string currentCntrlr = (string)ViewContext.RouteData.Values["controller"];
    string userName = (from c in User.Claims where c.Type == "name" select c.Value).FirstOrDefault();
    string id = (from c in User.Claims where c.Type == "sub" select c.Value).FirstOrDefault();
}

All of this is in the _Layout.cshtml and the @RenderBody comes from each View for your controller