【问题标题】:Create ViewModel for Navigation为导航创建 ViewModel
【发布时间】:2013-12-09 16:02:45
【问题描述】:

我有一个带有多个视图的 MVC 4 应用程序。 IE。产品、食谱、分销商和商店。

每个视图都基于一个模型。

让我们保持简单,说我所有的控制器都传递了一个类似的视图模型,看起来像我的 Product 操作:

public ActionResult Index()
{
    return View(db.Ingredients.ToList());
}

好的,这很好,没有问题。但是现在我的所有页面都正常工作了,我想更改我的导航(每个视图都有下拉菜单)以加载该模型中的项目。

所以我会有一个带有 4 个按钮(产品、食谱、分销商和商店)的导航。

当您滚动每个按钮(假设我们滚动产品按钮)时,下拉菜单会列出产品。

为此,我需要创建某种类型的 ViewModel,将所有 4 个模型组合在一起。显然我不能只为每个导航元素剪下一个 PartialView 并使用

@model IEnumerable<GranSabanaUS.Models.Products>

然后重复该下拉菜单的产品,因为那样导航只会在产品视图中起作用,而在其他任何地方都不起作用。

(After the solution) 是的 ROWAN 您在我创建的导航类型中是正确的,请参见此处:

【问题讨论】:

  • 您是否使用 jQuery 填充将用作下拉列表的 div?
  • 是的,更具体地说,我使用的是 Foundation 4 的顶栏导航元素
  • 我只需要帮助创建 viewModel 来将多个模型传递给一个视图,不需要 jQuery 结束的帮助
  • 如果我理解正确的话,你并没有为你的模型创建一个特定的类,对吧?您似乎想要创建一个包含 public db.Ingredients { get; 的“MenuContents”类。放; } (连同您的其他数据库项目)。我通常会创建一个名为“PopulateModel”的方法来读取数据库,并填写所有成员变量。在您的控制器中,您将创建此类的一个新实例并将其传递给您的局部视图。然后您的 cshtml 文件可以使用每个列表来填写它们的下拉列表。

标签: asp.net-mvc-4 navigation viewmodel partial-views


【解决方案1】:

简介

我将做一些假设,因为我没有所有信息。

我怀疑你想创建这样的东西:

分离视图

当您遇到“我如何将所有内容放入单个控制器/视图模型”的问题时,它可能做得太多,需要拆分。

不要将您的最终页面视为一个大视图 - 将视图分成较小的视图,以便它们做“一件事”。

例如,导航只是布局的一部分。您甚至可以进一步说,每个下拉菜单都是作为导航一部分的单个视图,依此类推。

导航概览

假设您有一个如下所示的_Layout.cshtml

<body>
    <div class="navbar">
        <ul class="nav">
            <li><a href="#">Products</a></li>
            <li><a href="#">Recipes</a></li>
        </ul>
    </div>

    @RenderBody()
</body>

如您所见,我们有一个简单的导航系统,然后渲染主体。我们面临的问题是:我们如何提取此导航并为其提供渲染所有内容所需的模型?

提取导航

让我们将导航提取到它自己的视图中。获取导航 HTML 并将其粘贴到名为 __Navigation.cshtml_ 的新视图中,并将其放在 ~/Views/Partials 下。

_Navigation.cshtml

<div class="navbar">
    <ul class="nav">
        <li><a href="#">Products</a></li>
        <li><a href="#">Recipes</a></li>
    </ul>
</div>

创建一个名为 PartialsController 的新控制器。创建一个新操作来调用我们的导航。

PartialsController.cs

[ChildActionOnly]
public class PartialsController : Controller
{
    public ActionResult Navigation()
    {
        return PartialView("_Navigation");
    }

}

更新我们的布局以调用导航。

_Layout.cshtml

<body>
    @Html.Action("Navigation", "Partials")

    @RenderBody()
</body>

现在我们的导航被分离成它自己的局部视图。它更加独立和模块化,现在更容易为其提供模型数据。

注入模型数据

假设我们有一些模型,例如您提到的模型。

public class Product { //... }
public class Recipe { //... }

让我们创建一个视图模型:

NavigationViewModel.cs

public class NavigationViewModel
{
    public IEnumerable<Product> Products { get; set; }
    public IEnumerable<Recipe> Recipes { get; set; }
}

让我们修正一下我们的行动:

PartialsController.cs

public ActionResult Navigation()
{
    NavigationViewModel viewModel;

    viewModel = new NavigationViewModel();
    viewModel.Products = db.Products;
    viewModel.Recipes = db.Recipes;

    return PartialView("_Navigation", viewModel);
}

最后,更新我们的观点:

_Navigation.cshtml

@model NavigationViewModel

<div class="navbar">
    <ul class="nav">

        @foreach (Product product in Model.Products)
        {
            @<li>product.Name</li>
        }

        @foreach (Recipe recipe in Model.Recipes)
        {
            @<li>recipe.Name</li>
        }
    </ul>
</div>

【讨论】:

  • 该死的。我非常感谢你的帮助和斯科蒂斯。我已经从你的两段代码中拿走了很多东西。这回答了我的问题,除此之外,您还花时间向像我这样需要解释的人解释。我再次感谢你们俩!让我仔细研究一下,我可能会有一个问题,但我对此表示怀疑。
  • 顺便说一句,我刚刚添加了我正在创建的实际导航的图像。你成功了!也很爱斯科蒂。再说一次,我不能说我多么感谢你的帮助。你们俩!
  • 效果很好。 :)
  • 我刚刚更新到 MVC 5,这个实现不再有效,我收到以下错误:The type or namespace name 'Recipe' could not be found (are you missing a using directive or an assembly reference?)
  • 我不得不切换答案。此实现在 MVC 5 中不起作用
【解决方案2】:
public class MenuContents
{
    public IEnumerable<Products> AllProducts { get; set; }
    public IEnumerable<Recepies> AllRecepies { get; set; }
    public IEnumerable<Distributors> AllDistributors { get; set; }
    public IEnumerable<Stores> AllStores { get; set; }

    private XXXDb db = new XXXUSDb();

    public void PopulateModel()
    {
        AllProducts = db.Products.ToList();
        AllRecepies = db.Recepies.ToList();
        AllDistributors = db.Distributors.ToList();
        AllStores = db.Stores.ToList();
    }
}

然后在你的控制器中

public ActionResult PartialWhatever()
{
    MenuContents model = new MenuContents();
    model.PopulateModel();

    return PartialView("PartialViewName", model);
}

然后在你的局部视图中

@Model MenuContents

... do whatever here

【讨论】:

  • 我是如此接近。我没有 PopulateModel 部分,并且在我的控制器中实现它的方式略有不同。现在看起来我看到了这一切。谢谢。一旦我开始工作,我会为你加油!谢谢斯科蒂!有时我们这些菜鸟只需要朝着正确的方向前进,而我在这里还没有看到一个问题可以轻松地为这种类型的 ViewModel 应用程序。
  • 所以在这种情况下,我不会通过我的正常视图传递它。相反,在那个视图中,我创建了一个局部视图并通过它引入它?
  • 您在原始帖子中提到您使用的是局部视图,所以这就是我使用局部视图的原因。它在常规视图中的工作方式相同,只需将其更改为 return View(model); return View 和 return PartialView 之间的唯一区别是 PartialView 不会返回任何 _layout.cshtml 内容。
  • 出于某种原因,Rowan 给出的实现只在 MVC 4 中有效,自从迁移到 MVC 5 后,我一直在自责,因为它破坏了我的 ViewModels。我放弃了一切并使用了您的实现,除了弄清楚如何构建 for 循环之外,它对我来说非常有效。谢谢,我已将此问题中的正确答案更改为您的。我会用正确的信息更新你的 for 循环,因为对于新手来说这很重要。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-08
  • 1970-01-01
相关资源
最近更新 更多