列表及导入导出
BasePagedListVM是框架中负责分页展示数据和导出的VM,它继承自BaseVM
建立一个BasePagedListVM
建立BasePagedListVM主要有以下几部
1. 定义继承自BasePagedListVM的类,将关联的Model作为泛型变量
2. 重写GetSearchQuery函数,将查询语句和逻辑写在这个函数里
3. 重写InitGridHeader函数,这个函数定义列表显示的列
4. 重写InitGridAction函数,这个函数定义列表中需要出现的操作按钮
下面以学校模型为例,展示如何编写一个简单的ListVM,学校模型的定义可以参考第一个模块
- public class SchoolListVM : BasePagedListVM<School, BaseSearcher>
- {
- protected override List<GridAction> InitGridAction()
- {
- return new List<GridAction>
- {
- this.MakeStandardAction("School", GridActionStandardTypesEnum.Create, "新建","", dialogWidth: 800),
- this.MakeStandardAction("School", GridActionStandardTypesEnum.Edit, "修改","", dialogWidth: 800),
- this.MakeStandardAction("School", GridActionStandardTypesEnum.Delete, "删除", "",dialogWidth: 800),
- this.MakeStandardAction("School", GridActionStandardTypesEnum.Details, "详细","", dialogWidth: 800),
- this.MakeStandardAction("School", GridActionStandardTypesEnum.BatchEdit, "批量修改","", dialogWidth: 800),
- this.MakeStandardAction("School", GridActionStandardTypesEnum.BatchDelete, "批量删除","", dialogWidth: 800),
- this.MakeStandardAction("School", GridActionStandardTypesEnum.Import, "导入","", dialogWidth: 800),
- this.MakeStandardExportAction(null,false,ExportEnum.Excel)
- };
- }
- protected override IEnumerable<IGridColumn<School>> InitGridHeader()
- {
- return new List<GridColumn<School>>{
- this.MakeGridHeader(x => x.SchoolCode),
- this.MakeGridHeader(x => x.SchoolName),
- this.MakeGridHeader(x => x.SchoolType),
- this.MakeGridHeaderAction(width: 200)
- };
- }
- public override IOrderedQueryable<School> GetSearchQuery()
- {
- var query = DC.Set<School>().OrderBy(x => x.ID);
- return query;
- }
- }
-
上面代码建立了一个简单的ListVM,它没有任何搜索条件,默认每页20行查询所有School的数据,并使用输出列表同样的逻辑来完成导出Excel。同时它定义了新建,修改等按钮
RecordsPerPage属性可以设置每页行数,默认是20行,NeedPage属性可以设定是否要进行分页
MakeStandardExportAction的作用是在列表上生成一个导出按钮
MakeGridHeaderAction的作用是在列表上增加一个操作列,操作列中出现的按钮是在InitGridAction中定义的所有ShowInRow为true的动作。当使用MakeStandardAction创建默认动作时,修改,删除和详细都是每行显示的
使用BasePagedListVM
在Controller中使用BasePagedListVM的步骤也是一目了然,请看下面的例子
- #region 搜索
- [ActionDescription("搜索")]
- public ActionResult Index()
- {
- var vm = CreateVM<SchoolListVM>();
- return PartialView(vm);
- }
- #endregion
-
必须使用CreateVM函数来创建ViewModel,而不要直接new。CreateVM函数会将当前Controller的Session,ModelState等信息传递给VM,并进行一些框架内部的操作
Searcher
上面的例子并没有任何搜索条件,真实场景中这种情况是很少的,要在列表中加入搜索条件,有两个步骤
1. 定义一个继承自BaseSearcher的类,将搜索条件作为类的属性,并把ListVM类的第二个泛型变量设定为这个Searcher
2. 在GetSearchQuery函数中使用Searcher的数据来编写查询语句
比如建立一个下面的Searcher用于搜索学校数据
- public class SchoolSearcher : BaseSearcher
- {
- [Display(Name = "学校编码")]
- public String SchoolCode { get; set; }
- [Display(Name = "学校名称")]
- public String SchoolName { get; set; }
- [Display(Name = "学校类型")]
- public SchoolTypeEnum? SchoolType { get; set; }
- }
-
然后修改SchoolListVM,将它的定义和SchoolSearcher关联 public class SchoolListVM : BasePagedListVM<School, SchoolSearcher>
最后修改GetSearchQuery,使用Searcher的数据
- public override IOrderedQueryable<School> GetSearchQuery()
- {
- var query = DC.Set<School>()
- .CheckContain(Searcher.SchoolCode, x=>x.SchoolCode)
- .CheckContain(Searcher.SchoolName, x=>x.SchoolName)
- .CheckEqual(Searcher.SchoolType, x=>x.SchoolType)
- .OrderBy(x => x.ID);
- return query;
- }
-
CheckContain,CheckEqual等是框架提供的便捷函数,用来替换where语句,并优化生成的查询语句
自定义输出
实际情况中,我们并不总是输出数据库中的原始数据,很多时候我们需要对原有数据进行加工,转换,或者显示数据库中并不存在的新列
请看下面的例子
- public class SchoolListVM : BasePagedListVM<School_View, SchoolSearcher>
- {
- protected override List<GridAction> InitGridAction()
- {
- return new List<GridAction>
- {
- this.MakeStandardAction("School", GridActionStandardTypesEnum.Create, "新建","", dialogWidth: 800),
- this.MakeStandardAction("School", GridActionStandardTypesEnum.Edit, "修改","", dialogWidth: 800),
- this.MakeStandardAction("School", GridActionStandardTypesEnum.Delete, "删除", "",dialogWidth: 800),
- this.MakeStandardAction("School", GridActionStandardTypesEnum.Details, "详细","", dialogWidth: 800),
- this.MakeStandardAction("School", GridActionStandardTypesEnum.BatchEdit, "批量修改","", dialogWidth: 800),
- this.MakeStandardAction("School", GridActionStandardTypesEnum.BatchDelete, "批量删除","", dialogWidth: 800),
- this.MakeStandardAction("School", GridActionStandardTypesEnum.Import, "导入","", dialogWidth: 800),
- this.MakeStandardExportAction(null,false,ExportEnum.Excel)
- };
- }
- protected override IEnumerable<IGridColumn<School_View>> InitGridHeader()
- {
- return new List<GridColumn<School_View>>{
- this.MakeGridHeader(x => x.SchoolCode),
- this.MakeGridHeader(x => x.SchoolName),
- this.MakeGridHeader(x => x.SchoolType),
- this.MakeGridHeader(x => x.Total).SetFormat(TotalFormat),
- this.MakeGridHeaderAction(width: 200)
- };
- }
- private string TotalFormat(School_View entity, object val)
- {
- return entity.SchoolCode + "," + entity.SchoolName + "," + entity.SchoolType;
- }
- public override IOrderedQueryable<School_View> GetSearchQuery()
- {
- var query = DC.Set<School>()
- .CheckContain(Searcher.SchoolCode, x=>x.SchoolCode)
- .CheckContain(Searcher.SchoolName, x=>x.SchoolName)
- .CheckEqual(Searcher.SchoolType, x=>x.SchoolType)
- .Select(x => new School_View
- {
- ID = x.ID,
- SchoolCode = x.SchoolCode,
- SchoolName = x.SchoolName,
- SchoolType = x.SchoolType
- })
- .OrderBy(x => x.ID);
- return query;
- }
- }
- public class School_View : School{
- public string Total {get;set;}
- }
-
上面代码中,我们新建了School_View类,用于扩展School来显示模型中并不存在的字段
然后我们通过在列上调用SetFormat方法来指定一个函数用于返回这列需要显示的数据
SetFormat接受的方法可以直接返回string,也可以返回List<ColumnFormatInfo>
ColumnFormatInfo的作用主要是方便我们生成一些按钮显示在列表中,如果返回string的话,比如我们需要根据某列数据生成一个按钮,点击按钮后弹出指定url的窗口,可能需要开发人员编写大量js
ColumnFormatInfo提供了很多扩展函数方便开发人员生成各种按钮,比如MakeDialogButton,MakeScriptButton,MakeDownloadButton等
以下例子演示了一个SetFormat的函数,它根据用户的照片ID,生成两个按钮,一个用来下载,一个用来弹出窗口直接显示照片
- private List<ColumnFormatInfo> PhotoIdFormat(FrameworkUser_View entity, object val)
- {
- return new List<ColumnFormatInfo>
- {
- ColumnFormatInfo.MakeDownloadButton(ButtonTypesEnum.Button,entity.PhotoId),
- ColumnFormatInfo.MakeViewButton(ButtonTypesEnum.Button,entity.PhotoId,640,480),
- };
- }
-
表格中使用控件
在项目中,我们还经常遇到使用grid来批量编辑数据的情况,
请看下面的例子
- public class StudentListVm : BasePagedListVM<Student,StudentSearcher>
- {
- public StudentListVm()
- {
- DetailGridPrix = "Students";
- }
- protected override List<GridAction> InitGridAction()
- {
- return new List<GridAction>
- {
- this.MakeStandardAction("Employee", GridActionStandardTypesEnum.AddRow, ""),
- this.MakeStandardAction("Employee", GridActionStandardTypesEnum.RemoveRow, ""),
- };
- }
- protected override IEnumerable<IGridColumn<Student>> InitGridHeader()
- {
- return new List<GridColumn<Student>>{
- this.MakeGridHeader(x => x.LoginName).SetEditType(EditTypeEnum.TextBox),
- this.MakeGridHeader(x => x.Name).SetEditType(EditTypeEnum.TextBox),
- this.MakeGridHeader(x => x.Sex).SetEditType(EditTypeEnum.ComboBox, typeof(Models.SexEnum).ToListItems(pleaseSelect:true)),
- this.MakeGridHeader(x => x.CellPhone).SetEditType(EditTypeEnum.TextBox),
- this.MakeGridHeader(x=>x.IsValid).SetEditType(EditTypeEnum.CheckBox)
- };
- }
- public override IOrderedQueryable<Student> GetSearchQuery()
- {
- List<Student> data = new List<Student>
- {
- new Student{ LoginName = "zhangsan", Name="张三", Sex= Models.SexEnum.Male, CellPhone="13012213483", ExcelIndex = 0, IsValid = true, ID = new Guid("6F5C2D15-4871-4083-B269-06F456A4F1B6")},
- new Student{ LoginName = "lisi", Name="李四", Sex= Models.SexEnum.Male, CellPhone="13075829654", ExcelIndex = 1, IsValid = false, ID = new Guid("9C7BC358-B8BD-4547-AFC1-11BF6F2B608B")},
- new Student{ LoginName = "wangwu", Name="王五", Sex= Models.SexEnum.Male, CellPhone="13098635100", ExcelIndex = 2, IsValid = true, ID = new Guid("3BF9217C-1ACF-4D80-9899-42CFDA4C8746")},
- new Student{ LoginName = "zhaoliu", Name="赵六", Sex= Models.SexEnum.Female, CellPhone="13035698123", ExcelIndex = 3, IsValid = false, ID = new Guid("0C7F6A24-A08D-46BD-86AC-6B6A391A9F04")},
- };
- var query = data.AsQueryable().Where(x=>
- (string.IsNullOrEmpty(Searcher.LoginName) || x.LoginName.Contains(Searcher.LoginName)) &&
- (string.IsNullOrEmpty(Searcher.Name) || x.Name.Contains(Searcher.Name)) &&
- (Searcher.Sex == null || x.Sex == Searcher.Sex)
- )
- .OrderBy(x => x.ExcelIndex);
- return query;
- }
- }
-
上面代码中,我们首先指定了DetailGridPrix字段,这个字段是告诉框架提交之后应该将数据保存在哪里,比如我们设定DetailGridPrix="Students",那么提交的时候,框架会使用Students[0].Id,Students[0].Name,Students[1].Id,Students[1].Name这种形式来提交数据
然后在InitGridAction方法中,我们定义了两个按钮,分别是AddRow和RemoveRow类型。这两个按钮负责动态给Grid添加或者删除行
最后再InitGridHeader方法中,我们使用SetEditType方法给每一列定义需要使用的控件
主要属性
属性 | 描述 |
---|---|
Searcher | 获取关联的搜索类 |
EntityList | 获取搜索结果 |
RecordsPerPage | 分页行数,默认时20条 |
NeedPage | 是否需要分页,默认为true |
SearcherMode | 搜索模式,用来判断当前搜索是普通列表,导出,批量操作等 |
属性 | 描述 |
---|
Searcher | 获取关联的搜索类 |
EntityList | 获取搜索结果 |
RecordsPerPage | 分页行数,默认时20条 |
NeedPage | 是否需要分页,默认为true |
SearcherMode | 搜索模式,用来判断当前搜索是普通列表,导出,批量操作等 |
主要函数
函数 | 描述 |
---|---|
InitGridAction() | 初始化列表需要显示的操作按钮 |
MakeStandardAction() | 根据默认设置生成添加,修改,删除,详细,导入的按钮 |
MakeStandardExportAction() | 生成导出Excel的按钮 |
InitGridHeader() | 初始化列表需要显示的列 |
GetSearchQuery() | 获取查询语句 |
GetExportQuery() | 获取导出时的查询语句,如不重写,默认调用GetSearchQuery |
GetCheckedExportQuery() | 获取勾选指定数据导出时的查询语句,如不重写,默认调用GetSearchQuery |
GetSelectorQuery() | 获取选择器模式下的查询语句,如不重写,默认调用GetSearchQuery |
GetBatchQuery | 获取批量模式下的查询语句,如不重写,默认调用GetSearchQuery |
函数 | 描述 |
---|
InitGridAction() | 初始化列表需要显示的操作按钮 |
MakeStandardAction() | 根据默认设置生成添加,修改,删除,详细,导入的按钮 |
MakeStandardExportAction() | 生成导出Excel的按钮 |
InitGridHeader() | 初始化列表需要显示的列 |
GetSearchQuery() | 获取查询语句 |
GetExportQuery() | 获取导出时的查询语句,如不重写,默认调用GetSearchQuery |
GetCheckedExportQuery() | 获取勾选指定数据导出时的查询语句,如不重写,默认调用GetSearchQuery |
GetSelectorQuery() | 获取选择器模式下的查询语句,如不重写,默认调用GetSearchQuery |
GetBatchQuery | 获取批量模式下的查询语句,如不重写,默认调用GetSear |