如何在FineUIMvc(ASP.NET MVC)视图中绑定多个模型?
起因

这是知识星球内的一个网友提出的,按理说ASP.NET MVC中一个视图只能绑定一个模型(Model),在视图顶部标识如下:
@model IEnumerable<FineUICore.Examples.Areas.DataModel.Models.Student>
视图中可以表格列可以使用RenderFieldFor来绑定:
@(F.Grid().IsFluid(true).CssClass("blockpanel").Title("表格").ShowHeader(true).ShowBorder(true).ID("Grid1").DataIDField("Id").DataTextField("Name")
.Columns(
F.RowNumberField(),
F.RenderFieldFor(m => m.Name),
F.RenderFieldFor(m => m.Gender).RendererFunction("renderGender").Width(80),
F.RenderFieldFor(m => m.EntranceYear),
F.RenderCheckFieldFor(m => m.AtSchool).RenderAsStaticField(true),
F.RenderFieldFor(m => m.Major).RendererFunction("renderMajor").ExpandUnusedSpace(true),
F.RenderFieldFor(m => m.Group).RendererFunction("renderGroup").Width(80),
F.RenderFieldFor(m => m.EntranceDate)
).DataSource(Model)
)
使用 RenderFieldFor 而不是 RenderField 列类型,好处是不需要书写每个列属性,FineUIMvc会查看模型属性的注解并自动完成属性赋值工作:

作为对比,我们看下使用 RenderField 时视图的标签定义:

问题是,如果页面上有多个表格需要绑定多个模型,该怎么办呢?
探索之路
抛开表格的数据绑定不谈,如果想向视图中传递多个数据,可以把一个作为模型对象传入,其他的作为ViewBag传入。
但是这个常见解决方法不适用于表格和表格的 RenderFieldFor 列,因为这个列是和视图模型密切相关的,在VS的智能提示帮助下,我们很容易发现这种关系:

可以看到传入 RenderFieldFor 的 lambda表达式左侧会被识别为模型的一部分,也就是说使用 RenderFieldFor 时模型类必须是 IEnumerable<> 泛型才对。
而一个视图不可能传入多个模型对象。
如果能将 模型和表格 绑定到一块,类似 ASP.NET WebForms 中的用户控件(UserControl),然后在主视图中引入这些绑定好的块岂不是很好?
其实ASP.NET MVC中有类似的解决方法,只不过不叫用户控件,而称为分部视图(PartialView),下面我们就用分部视图来实现上述功能。
1. 模型类(Student)上面已经介绍过了
2. 控制器,返回包含两个对象元组对象
public IActionResult Index()
{
var students = StudentHelper.GetSimpleStudentList();
var model = new Tuple<IEnumerable<Student>, IEnumerable<Student>>(students.Where(m => m.AtSchool), students.Where(m => !m.AtSchool));
return View(model);
}
3. 主视图
@{
var F = Html.F();
}
@using FineUICore.Examples.Areas.DataModel.Models;
@model Tuple<IEnumerable<Student>, IEnumerable<Student>>
@section body
{
@(Html.Partial("PartialGrid", Model.Item1, new ViewDataDictionary(ViewData) { { "__Title", "表格一(在校生)" } }))
<br />
@(Html.Partial("PartialGrid", Model.Item2, new ViewDataDictionary(ViewData) { { "__Title", "表格一(毕业生)" } }))
}
注意一下几点:
3.1 模型类型是:Tuple<IEnumerable<Student>, IEnumerable<Student>>
3.2 在视图中可以通过 Model.Item1 获取元组中的第一个对象,相应的 Model.Item2 获取第二个对象,从而省去了自定义类的麻烦
3.3 使用 Html.Partial 来渲染一个分部视图,传入三个参数:
----1. 分部视图的名称,会先在主视图所在目录中检索,如果找不到会转到 Shared 目录检索
----2. 传入分部视图的模型
----3. 额外的ViewData对象,如果需要引入多个分部视图,可以在为每个分部视图自定义显示数据
4. 分部视图(PartialGrid.cshtml)
@{
var F = Html.F();
}
@model IEnumerable<FineUICore.Examples.Areas.DataModel.Models.Student>
@{
var __Title = ViewData["__Title"].ToString();
}
@(F.Grid().IsFluid(true).CssClass("blockpanel").Title(__Title).ShowHeader(true).ShowBorder(true).DataIDField("Id").DataTextField("Name")
.Columns(
F.RowNumberField(),
F.RenderFieldFor(m => m.Name),
F.RenderFieldFor(m => m.Gender).RendererFunction("renderGender").Width(80),
F.RenderFieldFor(m => m.EntranceYear),
F.RenderCheckFieldFor(m => m.AtSchool).RenderAsStaticField(true),
F.RenderFieldFor(m => m.Major).RendererFunction("renderMajor").ExpandUnusedSpace(true),
F.RenderFieldFor(m => m.Group).RendererFunction("renderGroup").Width(80),
F.RenderFieldFor(m => m.EntranceDate)
).DataSource(Model)
)
首先从 ViewData 获取参数 __Title,然后在表格初始化时传入 .Title(__Title)。
需要注意的一点,这里不能将Grid的ID属性设为固定值,因为页面上可能会多次渲染此分部视图,比如下面的代码:
@(F.Grid().ID("Grid1").IsFluid(true).CssClass("blockpanel").Title(__Title).
如果页面上引入两次本分部视图,则页面上会有两个ID为 Grid1 的表格对象,这就搞错了!
解决办法有两个:
1. 不设置 Grid 的 ID 属性,这样 FineUIMvc 会在页面范围内自动生成一个不重复的
2. 在主视图调用 Html.Partial 时,传入一个类似 __Prefix 的属性,然后在分部视图中为表格ID加上这个前缀,有没有一种ASP.NET WebForms的感觉:
主视图:
@(Html.Partial("PartialGrid", Model.Item1, new ViewDataDictionary(ViewData) { { "__Prefix", "Connector1" }, { "__Title", "表格一(在校生)" } }))
<br />
@(Html.Partial("PartialGrid", Model.Item2, new ViewDataDictionary(ViewData) { { "__Title", "Connector2" }, { "__Title", "表格一(毕业生)" } }))
分部视图:
@(F.Grid().ID(ViewData["__Prefix"].ToString() + "_Grid1").IsFluid(true).CssClass("blockpanel").Title(__Title).
最终页面的显示效果:



小结
这篇文章讲解了如何在ASP.NET MVC视图中绑定多个模型,解决之道就是分部视图(PartialView),分部视图类似于ASP.NET WebForms中的用户控件,而不同之处在于分部视图不会给内部的控件ID加上所在的层次结构,因此如果一个页面中多次引入同一个分部视图就需要注意ID是否重复的问题了。
这个示例会更新到 FineUIMvc v5.3.0 版本中,查看 FineUIMvc 在线示例:http://mvc.fineui.com/
如何在FineUIMvc(ASP.NET MVC)视图中绑定多个模型?的更多相关文章
- asp.net mvc视图中使用entitySet类型数据时提示出错
asp.net mvc5视图中使用entitySet类型数据时提示以下错误 检查了一下引用,发现已经引用了System.Data.Linq了,可是还是一直提示出错, 后来发现还需要在Views文件夹下 ...
- ASP.NET MVC视图中的@Html.xxx(...)
问题 在视图页中@Html.xxx(...)是什么?如何被执行? 如下图所示: 解疑 视图页中@Html.xxx(...)涉及的内容有: 视图页被编译后的类继承自 WebViewPage<T&g ...
- asp.net mvc视图中嵌套分部视图
asp.net mvc中Layout相当于webForm中母版页,分部视图相当于webForm中的用户控件. 下面例子是一个视图如何嵌套分部视图: A是分部视图,B是一般视图(A,B中的代码省略) 我 ...
- MVC视图中的@Html.xxx(...)
ASP.NET MVC视图中的@Html.xxx(...) 问题 在视图页中@Html.xxx(...)是什么?如何被执行? 如下图所示: 解疑 视图页中@Html.xxx(...)涉及的内容有: ...
- [转]在 ASP.NET MVC 4 中创建为移动设备优化的视图
原文链接 https://msdn.microsoft.com/zh-cn/magazine/dn296507.aspx 如果深入探讨有关编写移动设备网站的常识性考虑因素,会发现其中有一种内在矛盾. ...
- ASP.NET MVC 4中如何为不同的浏览器自适应布局和视图
在ASP.NET MVC 4中,可以很简单地实现针对不同的浏览器自适应布局和视图.这个得归功于MVC中的"约定甚于配置"的设计理念. 默认的自适应 MVC 4自动地为移动设备浏览器 ...
- 【初学者指南】在ASP.NET MVC 5中创建GridView
介绍 在这篇文章中,我们将会学习如何在 ASP.NET MVC 中创建一个 gridview,就像 ASP.NET Web 表单中的 gridview 一样.服务器端和客户端有许多可用的第三方库,这些 ...
- ASP.NET MVC 视图(五)
ASP.NET MVC 视图(五) 前言 上篇讲解了视图中的分段概念.和分部视图的使用,本篇将会对Razor的基础语法简洁的说明一下,前面的很多篇幅中都有涉及到视图的调用,其中用了很多视图辅助器,也就 ...
- ASP.NET MVC 视图(四)
ASP.NET MVC 视图(四) 前言 上篇对于利用IoC框架对视图的实现进行依赖注入,最后还简单的介绍一下自定义的视图辅助器是怎么定义和使用的,对于Razor语法的细节和辅助器的使用下篇会说讲到, ...
随机推荐
- 华为云提供针对Nuget包管理器的缓存加速服务
在Visual Studio 2013.2015.2017中,使用的是Nuget包管理器对第三方组件进行管理升级的.而且 Nuget 是我们使用.NET Core的一项基础设施,.NET的软件包管理器 ...
- VS2013 百度云资源以及密钥
https://pan.baidu.com/s/1eu3XycWO8fWItmkFeYNv9w提取码:dy9r 密钥:BWG7X-J98B3-W34RT-33B3R-JVYW9 vs2015 http ...
- PHP内核之旅-4.可变长度的字符串
PHP 内核之旅系列 PHP内核之旅-1.生命周期 PHP内核之旅-2.SAPI中的Cli PHP内核之旅-3.变量 PHP内核之旅-4.字符串 PHP内核之旅-5.强大的数组 PHP内核之旅-6.垃 ...
- .Net Webapi SignalR与微信小程序的交互
.Net Webapi SignalR与微信小程序的交互 一.SignalR与Webapi 1.SignalR的安装: Signalr与跨域仅需要安装两个开源库 Microsoft.Owin.Cors ...
- .NET Core微服务之基于Ocelot+Butterfly实现分布式追踪
Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.什么是Tracing? 微服务的特点决定了功能模块的部署是分布式的,以往在单应用环境下,所有的业务都在同一个服务器上,如果服务器出现错 ...
- Linux自定义分隔符IFS引发的文本处理问题
需求是检查指定应用的某些配置所以就写了个脚本,数据文件的内容是这样的:应用名称|IP|端口 多个IP用空格,这样可以生成数组.这个文件的数据是通过部署平台的API获取后自己组装的. #!/bin ...
- Python的线程池
#!/usr/bin/env python # -*- coding: utf-8 -*- """ concurrent 用于线程池和进程池编程而且更加容易,在Pytho ...
- 微信公众号开发C#系列-8、自定义菜单及菜单响应事件的处理
1.概述 自定义菜单能够帮助公众号丰富界面,让用户更好更快地理解公众号的功能.菜单分为默认菜单与个性化菜单.个性化菜单接口是为了帮助公众号实现灵活的业务运营,开发者可以通过该接口,让公众号的不同用户群 ...
- C# 10分钟完成百度人脸识别——入门篇
嗨咯,小编在此祝大家新年快乐财多多! 今天我们来盘一盘人脸注册.人脸识别等相关操作,这是一个简单入门教程. 话不多说,我们进入主题: 完成人脸识别所需的步骤: 注册百度账号api,创建自己的应用: 创 ...
- Writing a Simple Publisher and Subscriber
用c++实现一个publisher/subscriber publisher #include "ros/ros.h" #include "std_msgs/String ...