敏捷思维学习Ext.Net MVC--3.5Form表单组件之下拉菜单(ComboBox)
下面我们来新建一个较为复杂的字段—下拉菜单字段,我们以一个公司的员工所属的部门为例来介绍这个字段。为了达到简化的目的我们假设这个员工目前只有姓名和所属部门两个属性。这里我们引入UML类图来帮助我们设计类。在这里我们也会一点点介绍UML的知识。将人员和部门的类抽象出来如下图所示:
部门类有ID、Name这两个属性,和一个GetAll()动作用来得到所有的部门。员工类则有Name、department这两个属性其中属性department是Department类的对象,通常一个类的对象作为另一个类的成员变量时这两个类之间为关联关系(Association),Employee类的GetAll()动作是用来得到所有员工的。有了类的UML类图我们就有了设计类的图纸了。
一、我们在FormModel中新建Department类如下:
public class CDepartment
{
public int ID { get; set; }
public string Name { get; set; }
public static List<CDepartment> GetAll()//(1)
{
return new List<CDepartment>
{
new CDepartment{ID=1,Name="计算机"},
new CDepartment{ID=2,Name="机械工程"},
new CDepartment{ID=3,Name="国际贸易"},
new CDepartment{ID=4,Name="金融管理"},
};
}
}
ID和Name是Department类的属性项这里不用多说。(1) GetAll()函数是该类的动作函数,用来返回所有的部门列表我们这里新建了四个部门返回,注意返回的列表是从0开始编码的,在我们读取数据的时候一定要注意。
二、在FormModel中新建Employee类如下:
public class Employee
{
[Field(FieldType = typeof(Ext.Net.Hidden))]
public int ID { get; set; }
public string Name
{
get;
set;
}
[UIHint("Department")]//(1)
public CDepartment Department
{
get;
set;
}
public static List<Employee> GetAll()//(2)
{
return new List<Employee>
{
new Employee
{
ID=1,
Name="惹尘",
Department=CDepartment.GetAll()[0]//(3)
},
new Employee
{
ID=2,
Name="大钱",
Department=CDepartment.GetAll()[2]//(4)
}
};
}
}
(1)使用UIHint建立Department模板,至于模板的路径和内容我们接下来再将,这里需要注意的是一定要引入UIHint的命名空间:using System.ComponentModel.DataAnnotations;
(2)Employee类的GetAll()函数用列表的方式返回所用员工。这里的员工我们也以新建的方式建立。(3)、(4)注意返回的部门列表的索引起始值为0,也就是惹尘的部门是“计算机”大钱则是第三个部门“国际贸易”的员工。
三、建立UIHint的Department模板,该模板的默认路径是View/Shared/ EditorTemplates/Department.cshtml,打开View下的Shared文件夹发现没有EditorTemplates文件夹,先新建此文件夹,然后在文件夹中新建Department.cshtml文件,注意该文件的名称与[UIHint("Department")]中字符串的值和public CDepartment Department的属性名“Department”一样。将该文件中的内容替换为如下内容:
@using ExtNetMvcExample.Models//(1)
@model CDepartment//(2)
@(
Html.X().ComboBoxFor(m=>m.ID)//(3)
.Items(CDepartment.GetAll().Select(d=>new ListItem(d.Name,d.ID)))//(4)
.FieldLabel("所属部门")
.SimpleSubmit(true)//(5)
.Listeners(l =>//(6)
{
l.Select.Handler = "this.next().setValue(this.getRawValue());";//(7)
})
)
@(
Html.X().HiddenFor(m=>m.Name) //(8)
)
(1)、(2)分别为引入命名空间和引入模型,在以前的例子中我们都是使用一条语句引入模型如:@using ExtNetMvcExample.Models.Department,而这里却将一句话分解成了两句,这样做的原因是我们除了使用模型Department外,我们还要使用其中的静态函数GetAll(),此函数只能通过类名进行调用,只有将ExtNetMvcExample.Models命名空间引入进来我们才可以使用类名。(3)使用Department的ID属性建立ComboBox,注意这里建立的不仅仅是是一个Name为ID的Combox,系统在View端会自动生成如下javaScript代码(利用Firefox的FireBug在前台调试所得,网上有关于FireBug的详细描述,有关Extjs的知识可以参考黄灯桥老师ExtJs权威指南):
{id:"Department_ID",xtype:"combobox",fieldLabel:"Department",name:"Department.ID",allowBlank:false,blankText:"ID 字段是必需的。",
selectedItems: [{value:1}],simpleSubmit:true,queryMode:"local",
store:[[1,"计算机"],[2,"机械工 程"],[3,"国际贸易"],[4,"金融管理"]],
listeners:{select:{fn:function(item,records) {this.next().setValue(this.getRawValue());}}}}, {id:"Department_Name",xtype:"hiddenfield",name:"Department.Name",value:" 计算机"}]
我们注意到系统自动生成了不仅仅是一个name为"Department.ID"的combobox字段,而且生成了一个name为"Department.Name"的隐藏字段,该字段通过(6) (7)设置的动作处理函数来赋值,这是我们也可以对(6) (7)中的内容进行解释,(6)给combobox字段设置了时间监听函数,给字段选择新的值(l.Select),添加了处理函数(Handler),Handler函数的内容为后面的字符串"this.next().setValue(this.getRawValue());",其中this指的是combobox字段;next()指的是选择与元素同层的下一个元素,也就是name为"Department.Name"的隐藏字段,setValue(this.getRawValue())给该字段赋值,赋的值为combobox字段store中对应的部门名称(Name)。这样在提交数据时就能改变Employee对象中CDepartment对象Department的Name属性。(8)是必须设定的,因为当表单提交时Department的Name属性一般是通过ID属性恢复出来的,当然在Ext.Net MVC中是通过增加了name为"Department.Name"的隐藏字段直接提交给后台的,这里comobox的只要提交ID即可。
四、在控制器FormController中添加以下函数:
public ActionResult MyComboBox()
{
return View(Employee.GetAll()[0]); //(1)
}
(1)传递给View界面第一个Employee对象,也就是:
new Employee
{
ID=1,
Name="惹尘",
Department=CDepartment.GetAll()[0]//(3)
}
五、右键添加MyComboBox.cshtml文件将文件中的内容替换如下:
@model ExtNetMvcExample.Models.Employee
@{
Layout = null;
//Layout = "~/Views/Shared/_BaseLayout.cshtml";
}
<!DOCTYPE html>
<html>
<head>
<title>ComboBoxField</title>
</head>
<body>
@Html.X().ResourceManager()
@(
Html.X().FormPanelFor(m=>m) //(1)
.BodyPadding(10)
.Margin(10)
.DefaultAnchor("100%")
.Width(300)
.Buttons(Html.X().Button()
.Text("提交")
.DirectClickUrl(Url.Action("ComboxSubmit"))//(2)
)
)
</body>
</html>
(1)这里我们采用了更高效的表单生成方法FormPanelFor(m=>m)可以复杂的字段用UIHint定义好,然后用类型直接生成表单,UIHint定义的字段也可以得到很好的重用,系统的模块化也得到增强。(2)设置数据提交的路由为ComboxSubmit。
六、在FormController中添加数据处理函数
public ActionResult ComboxSubmit(Employee e) //(1)
{
X.Msg.Alert("Employee", JSON.Serialize(e)).Show();//(2)
return this.Direct();
}
(1)用Employee类型接受前端传递过来的数据。(2)将前端传递过来的数据序列化为Json字符串并传回前端显示。
运行界面如下图所示:
返回数据的界面如下: