视图中的多个模型

我想在一个视图中有2个模型。该页包含LoginViewModelRegisterViewModel

如。

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)
}
469238 次浏览

有很多方法……

  1. 与你的BigViewModel 你可以:

    @model BigViewModel
    @using(Html.BeginForm()) {
    @Html.EditorFor(o => o.LoginViewModel.Email)
    ...
    }
    
  2. you can create 2 additional views

    Login.cshtml

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

    并注册。cshtml 同样的事情

    创建之后,你必须在主视图中渲染它们,并将viewmodel/viewdata传递给它们

    所以它可以是这样的:

    @{Html.RenderPartial("login", ViewBag.Login);}
    @{Html.RenderPartial("register", ViewBag.Register);}
    

    @{Html.RenderPartial("login", Model.LoginViewModel)}
    @{Html.RenderPartial("register", Model.RegisterViewModel)}
    
  3. using ajax parts of your web-site become more independent

  4. iframes, but probably this is not the case

我建议使用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将是驻留在当前视图文件夹或共享文件夹中的用户控件,并像这样:

/视图/共享/登录。cshtml(或/Views/MyView/Login.cshtml)

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

/视图/共享/注册。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"})
}

请注意,我在构建表单时手动更改了每个属性的Name属性。需要这样做,否则在将值发送到相关方法进行处理时,它将不能正确地映射到方法的model类型参数。我建议使用单独的方法分别处理这些表单,对于本例,我使用了Login1和Login2方法。Login1方法需要一个RegisterViewModel类型的参数,而Login2方法需要一个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的两个实例,然后将其传递给视图。

一个简单的方法

我们可以先呼叫所有型号

@using project.Models

然后发送你的模型与viewbag

// for list
ViewBag.Name = db.YourModel.ToList();


// for one
ViewBag.Name = db.YourModel.Find(id);

在视图中

// for list
List<YourModel> Name = (List<YourModel>)ViewBag.Name ;


//for one
YourModel Name = (YourModel)ViewBag.Name ;

然后很容易使用这个模型

我想说我的解决方案就像这个stackoverflow页面上提供的答案:ASP。NET MVC 4,多个模型在一个视图?

然而,在我的情况下,他们在他们的控制器中使用的linq查询不适合我。

这就是所谓的查询:

var viewModels =
(from e in db.Engineers
select new MyViewModel
{
Engineer = e,
Elements = e.Elements,
})
.ToList();

因此,“在您的视图中,只需指定您正在使用视图模型的集合”对我来说也不适用。

然而,稍微改变一下这个解决方案确实对我有用。这是我的解决方案,希望对大家有所帮助。

这是我的视图模型,我知道我将只有一个团队,但该团队可能有多个板(顺便说一下,我在我的Models文件夹中有一个ViewModels文件夹,因此有命名空间):

namespace TaskBoard.Models.ViewModels
{
public class TeamBoards
{
public Team Team { get; set; }
public List<Board> Boards { get; set; }
}
}

这是我的控制器。这是与上面引用的链接中的解决方案最显著的区别。我构建了ViewModel以不同的方式发送到视图。

public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}


TeamBoards teamBoards = new TeamBoards();
teamBoards.Boards = (from b in db.Boards
where b.TeamId == id
select b).ToList();
teamBoards.Team = (from t in db.Teams
where t.TeamId == id
select t).FirstOrDefault();


if (teamBoards == null)
{
return HttpNotFound();
}
return View(teamBoards);
}

在我看来,我没有将它指定为列表。我只做@model taskboard。models。viewmodels。“然后,当我迭代团队的板时,我只需要每个。以下是我的观点:

@model TaskBoard.Models.ViewModels.TeamBoards


@{
ViewBag.Title = "Details";
}


<h2>Details</h2>


<div>
<h4>Team</h4>
<hr />




@Html.ActionLink("Create New Board", "Create", "Board", new { TeamId = @Model.Team.TeamId}, null)
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => Model.Team.Name)
</dt>


<dd>
@Html.DisplayFor(model => Model.Team.Name)
<ul>
@foreach(var board in Model.Boards)
{
<li>@Html.DisplayFor(model => board.BoardName)</li>
}
</ul>
</dd>


</dl>
</div>
<p>
@Html.ActionLink("Edit", "Edit", new { id = Model.Team.TeamId }) |
@Html.ActionLink("Back to List", "Index")
</p>

我对ASP还是个新手。NET MVC,所以我花了一点时间来弄清楚。所以,我希望这篇文章能帮助人们在更短的时间内为他们的项目找到答案。: -)

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

   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)
  1. 在你的模型和属性LoginViewModelRegisterViewModel中创建一个新类:

    public class UserDefinedModel()
    {
    property a1 as LoginViewModel
    property a2 as RegisterViewModel
    }
    
  2. Then use UserDefinedModel in your view.

将这个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

我是否需要创建另一个包含这两个视图的视图?

回答:不

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

是的,你可以使用元组(带来魔术在视图有多个模型)。

代码:

 @model Tuple<LoginViewModel, RegisterViewModel>




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




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

你总是可以在ViewBag或View Data中传递第二个对象。

我的建议是创建一个大的视图模型:

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

在你的索引。Cshtml,如果你有两个部分:

@addTagHelper *,Microsoft.AspNetCore.Mvc.TagHelpers
@model .BigViewModel


@await Html.PartialAsync("_LoginViewPartial", Model.LoginViewModel)


@await Html.PartialAsync("_RegisterViewPartial ", Model.RegisterViewModel )

在控制器中:

model=new BigViewModel();
model.LoginViewModel=new LoginViewModel();
model.RegisterViewModel=new RegisterViewModel();

这是一个使用IEnumerable的简化示例。

我在视图上使用了两个模型:一个是带有搜索条件的表单(SearchParams模型),另一个是用于显示结果的网格,我还纠结于如何在同一个视图上添加IEnumerable模型和另一个模型。这是我想到的,希望能帮助到一些人:

@using DelegatePortal.ViewModels;


@model SearchViewModel


@using (Html.BeginForm("Search", "Delegate", FormMethod.Post))
{


Employee First Name
@Html.EditorFor(model => model.SearchParams.FirstName,
new { htmlAttributes = new { @class = "form-control form-control-sm " } })


<input type="submit" id="getResults" value="SEARCH" class="btn btn-primary btn-lg btn-block" />


}
<br />
@(Html
.Grid(Model.Delegates)
.Build(columns =>
{
columns.Add(model => model.Id).Titled("Id").Css("collapse");
columns.Add(model => model.LastName).Titled("Last Name");
columns.Add(model => model.FirstName).Titled("First Name");
})
< p >… ) < / p >

SearchViewModel.cs:

namespace DelegatePortal.ViewModels
{
public class SearchViewModel
{
public IEnumerable<DelegatePortal.Models.DelegateView> Delegates { get; set; }


public SearchParamsViewModel SearchParams { get; set; }
....

DelegateController.cs:

// GET: /Delegate/Search
public ActionResult Search(String firstName)
{
SearchViewModel model = new SearchViewModel();
model.Delegates = db.Set<DelegateView>();
return View(model);
}


// POST: /Delegate/Search
[HttpPost]
public ActionResult Search(SearchParamsViewModel searchParams)
{
String firstName = searchParams.FirstName;
SearchViewModel model = new SearchViewModel();


if (firstName != null)
model.Delegates = db.Set<DelegateView>().Where(x => x.FirstName == firstName);


return View(model);
}

SearchParamsViewModel.cs:

namespace DelegatePortal.ViewModels
{
public class SearchParamsViewModel
{
public string FirstName { get; set; }
}
}