我想在一个视图中有2个模型。页面包含LoginViewModel和RegisterViewModel。

e.g.

public class LoginViewModel
{
    public string Email { get; set; }
    public string Password { get; set; }
}

public class RegisterViewModel
{
    public string Name { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
}

我需要做另一个ViewModel持有这2个ViewModel吗?

public BigViewModel
{
    public LoginViewModel LoginViewModel{get; set;}
    public RegisterViewModel RegisterViewModel {get; set;}
}

我需要将验证属性带到视图中。这就是为什么我需要ViewModels。

有没有其他的方法,比如(没有BigViewModel):

 @model ViewModel.RegisterViewModel
 @using (Html.BeginForm("Login", "Auth", FormMethod.Post))
 {
        @Html.TextBoxFor(model => model.Name)
        @Html.TextBoxFor(model => model.Email)
        @Html.PasswordFor(model => model.Password)
 }

 @model ViewModel.LoginViewModel
 @using (Html.BeginForm("Login", "Auth", FormMethod.Post))
 {
        @Html.TextBoxFor(model => model.Email)
        @Html.PasswordFor(model => model.Password)
 }

当前回答

在你的模型和LoginViewModel和RegisterViewModel属性中创建一个新类: 公共类UserDefinedModel() { 属性a1作为LoginViewModel property a2 as RegisterViewModel } 然后在视图中使用UserDefinedModel。

其他回答

使用包含多个视图模型的视图模型:

   namespace MyProject.Web.ViewModels
   {
      public class UserViewModel
      {
          public UserDto User { get; set; }
          public ProductDto Product { get; set; }
          public AddressDto Address { get; set; }
      }
   }

你认为:

  @model MyProject.Web.ViewModels.UserViewModel

  @Html.LabelFor(model => model.User.UserName)
  @Html.LabelFor(model => model.Product.ProductName)
  @Html.LabelFor(model => model.Address.StreetName)

我建议使用Html。RenderAction和PartialViewResults来完成这个;它将允许您显示相同的数据,但每个部分视图仍然有一个单一的视图模型,并消除了对BigViewModel的需要

你的视图包含如下内容:

@Html.RenderAction("Login")
@Html.RenderAction("Register")

其中Login和Register都是你控制器中的动作,定义如下:

public PartialViewResult Login( )
{
    return PartialView( "Login", new LoginViewModel() );
}

public PartialViewResult Register( )
{
    return PartialView( "Register", new RegisterViewModel() );
}

Login & Register将是位于当前View文件夹或共享文件夹中的用户控件,并像这样:

/views/Shared/Login.cshtml: (或 /views/MyView/Login.cshtml)

@model LoginViewModel
@using (Html.BeginForm("Login", "Auth", FormMethod.Post))
{
    @Html.TextBoxFor(model => model.Email)
    @Html.PasswordFor(model => model.Password)
}

/views/Shared/Register.cshtml: (或 /views/MyView/Register.cshtml)

@model ViewModel.RegisterViewModel
@using (Html.BeginForm("Login", "Auth", FormMethod.Post))
{
    @Html.TextBoxFor(model => model.Name)
    @Html.TextBoxFor(model => model.Email)
    @Html.PasswordFor(model => model.Password)
}

你有一个单独的控制器动作,每个动作都有视图和视图文件每个动作都完全不同,不依赖于其他任何东西。

另一种方法是使用:

@model Tuple<LoginViewModel,RegisterViewModel>

我已经在另一个例子中解释了如何在视图和控制器中使用这个方法:在ASP MVC 3的一个视图中有两个模型

在你的情况下,你可以使用下面的代码来实现它:

在视图中:

@using YourProjectNamespace.Models;
@model Tuple<LoginViewModel,RegisterViewModel>

@using (Html.BeginForm("Login1", "Auth", FormMethod.Post))
{
        @Html.TextBoxFor(tuple => tuple.Item2.Name, new {@Name="Name"})
        @Html.TextBoxFor(tuple => tuple.Item2.Email, new {@Name="Email"})
        @Html.PasswordFor(tuple => tuple.Item2.Password, new {@Name="Password"})
}

@using (Html.BeginForm("Login2", "Auth", FormMethod.Post))
{
        @Html.TextBoxFor(tuple => tuple.Item1.Email, new {@Name="Email"})
        @Html.PasswordFor(tuple => tuple.Item1.Password, new {@Name="Password"})
}

Note that I have manually changed the Name attributes for each property when building the form. This needs to be done, otherwise it wouldn't get properly mapped to the method's parameter of type model when values are sent to the associated method for processing. I would suggest using separate methods to process these forms separately, for this example I used Login1 and Login2 methods. Login1 method requires to have a parameter of type RegisterViewModel and Login2 requires a parameter of type LoginViewModel.

如果需要一个actionlink,你可以使用:

@Html.ActionLink("Edit", "Edit", new { id=Model.Item1.Id })

在控制器的视图方法中,需要创建一个类型为Tuple的变量,然后传递给视图。

例子:

public ActionResult Details()
{
    var tuple = new Tuple<LoginViewModel, RegisterViewModel>(new LoginViewModel(),new RegisterViewModel());
    return View(tuple);
}

或者您可以用值填充LoginViewModel和RegisterViewModel的两个实例,然后将其传递给视图。

将这个ModelCollection.cs添加到您的模型中

using System;
using System.Collections.Generic;

namespace ModelContainer
{
  public class ModelCollection
  {
   private Dictionary<Type, object> models = new Dictionary<Type, object>();

   public void AddModel<T>(T t)
   {
      models.Add(t.GetType(), t);
   }

   public T GetModel<T>()
   {
     return (T)models[typeof(T)];
   }
 }
}

控制器:

public class SampleController : Controller
{
  public ActionResult Index()
  {
    var model1 = new Model1();
    var model2 = new Model2();
    var model3 = new Model3();

    // Do something

    var modelCollection = new ModelCollection();
    modelCollection.AddModel(model1);
    modelCollection.AddModel(model2);
    modelCollection.AddModel(model3);
    return View(modelCollection);
  }
}

视图:

enter code here
@using Models
@model ModelCollection

@{
  ViewBag.Title = "Model1: " + ((Model.GetModel<Model1>()).Name);
}

<h2>Model2: @((Model.GetModel<Model2>()).Number</h2>

@((Model.GetModel<Model3>()).SomeProperty

在你的模型和LoginViewModel和RegisterViewModel属性中创建一个新类: 公共类UserDefinedModel() { 属性a1作为LoginViewModel property a2 as RegisterViewModel } 然后在视图中使用UserDefinedModel。