OSharp是什么?

  OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现。与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现。依赖注入、ORM、对象映射、日志、缓存等等功能,都只定义了一套最基础最通用的抽象封装,提供了一套统一的API、约定与规则,并定义了部分执行流程,主要是让项目在一定的规范下进行开发。所有的功能实现端,都是通过现有的成熟的第三方组件来实现的,除了EntityFramework之外,所有的第三方实现都可以轻松的替换成另一种第三方实现,OSharp框架正是要起隔离作用,保证这种变更不会对业务代码造成影响,使用统一的API来进行业务实现,解除与第三方实现的耦合,保持业务代码的规范与稳定。

本文已同步到系列目录:OSharp快速开发框架解说系列

EasyUI复杂布局

  接上篇,前面我们已经定义了一个 datagrid父视图 _DataGridLayout.cshtml,实现一个表格是相当的容易。但是,实际业务中,并非所有的数据列表并非只是单一的datagrid列表,还可能需要把datagrid与其他组件配合使用,比如角色信息是来源于各个组织机构的,就需要增加一个组织机构的分类,来更好的管理各种角色。最终效果图如下:
  

  来分析一下这个页面,不难看出,需要将选项卡Tab的内容页拆分成另外一个由左+内容的 easyui-layout 构成的布局页,左部分是组织机构的树型导航栏,右边是相应的角色列表。

  我们先来分析一下前后的html变化,只有一个datagrid的时候,html很简单,只有一行:

 <div id="grid-roles"></div>

  要满足上面的需求,html变成了:

 <div id="layout-roles" class="easyui-layout" data-options="fit:true">
<div data-options="region:'west', split:true, minWidth:80, width:150, title:'组织机构'">
<ul id="tree-organizations" class="easyui-tree"></ul>
</div>
<div data-options="region:'center', border:false">
<div id="grid-roles"></div>
</div>
</div>

  这个而已,原先的 _DataGridLayout.cshtml 还能胜任吗?答案是肯定的,因为我们已经预先做好了准备,_DataGridLayout.cshtml 中有如下定义:

  

  只需要把 #grid-roles 前后的代码分别回到 headHtml 与 footHtml 两个Section中,就能满足需求,在Views\Roles\Index.cshtml中添加如下代码:

  

  注意,在html已经被拆分成了两部分,单一部分肯定是不闭合的,会处于报错状态,但一定要保证组合起来之后是闭合的,才能生成正确的 html。

  当然,还要按需要添加处理新添加的 easyui-layout 和 easyui-tree 的 javascript 代码,这就要用到 _DataGridLayout.cshtml 中定义的 startfunction() 与 endfunction() 两个方法了,要添加的代码也很简单,只要选择组织机构的树节点的时候变更datagrid的URL即可:

  

  综合之后,角色列表视图的代码组织如下:

 @{
ViewBag.Title = "角色信息列表";
Layout = "~/Areas/Admin/Views/Shared/_DataGridLayout.cshtml"; ViewBag.GridId = "roles";
ViewBag.GridDataUrl = Url.Action("GridData");
ViewBag.NodeDataUrl = Url.Action("NodeData", "Organizations");
}
@section customScript
{
<script type="text/javascript">
columns = [[
{ field: "Id", title: "编号", width: 40, halign: "center", align: "right", sortable: true },
{ field: "Name", title: "角色名", width: 150, sortable: true },
{ field: "Remark", title: "角色描述", width: 150, sortable: true },
{ field: "CreatedTime", title: "创建时间", width: 150, halign: "center", align: "center", sortable: true, formatter: function (value) { return $.osharp.tools.formatDate(value); } }
]]; endfunction = function () {
var $tree = $("#tree-@ViewBag.TreeId");
$tree.tree({
url: "@ViewBag.NodeDataUrl",
onSelect:function(node) {
grid.datagrid({
url: "@ViewBag.GridDataUrl/" + node.id
});
}
});
};
</script>
}
@section headHtml
{
<div id="layout-@ViewBag.GridId" class="easyui-layout" data-options="fit:true">
<div data-options="region:'west', split:true, minWidth:80, width:150, title:'组织机构'">
<ul id="tree-@ViewBag.TreeId" class="easyui-tree"></ul>
</div>
<div data-options="region:'center', border:false">
}
@section footHtml
{
</div>
</div>
}

  运行效果如图:

  

EasyUI动态工具栏

  表格的工具栏  的项,由 _DataGridLayout.cshtml 中的  string toolbarItem = ViewBag.ToolbarItem ?? "add,edit,save,cancel,delete"; 控制,需要重新定义的时候,在 子视图中重新定义ViewBag.ToolbarItem 即可。生成项的代码如下:

 var toolbarData = [
@if (toolbarItem.Contains("add"))
{
@:{ text: "增加", iconCls: "icon-add", handler: addNewRow },
}
@if (toolbarItem.Contains("edit"))
{
<text>
{ text: "编辑", iconCls: "icon-edit", handler: beginEdit },
"-",
</text>
}
@if (toolbarItem.Contains("save"))
{
@:{ text: "保存", iconCls: "icon-save", handler: saveChanges },
}
@if (toolbarItem.Contains("cancel"))
{
<text>
{ text: "取消", iconCls: "icon-undo", handler: cancelEdit },
"-",
</text>
}
@if (toolbarItem.Contains("delete"))
{
@:{ text: "删除", iconCls: "icon-remove", handler: deleteRows },
}
];

  如果需要给添加额外表格操作,可以在子视图中重写 startfunction() 方法,添加相应的按钮项和功能函数即可:

 startfunction = function () {
//导出
function exportRoles() {
$.osharp.easyui.msg.info("导出角色数据");
}
toolbarData.push({ text: "导出", iconCls: "pic_50", handler: exportRoles });
};

  这样,就能根据用户的权限动态的决定用户有哪些可用功能,运行效果如下:

  

EasyUI增删改操作

前端部分

  在本示例中,表格数据的操作尽量使用 行内编辑 的方式来进行,如部分数据需要别的方式(比如弹出窗口的编辑方式),可在子视图中对工具栏按钮事件进行重写。

  行内编辑,需要在子视图的 columns 信息中添加编辑及数据验证的相关设置 editor,具体参考 easyui 的api说明,这里略过,如下:

 columns = [[
{ field: "Id", title: "编号", width: 40, halign: "center", align: "right", sortable: true },
{ field: "Name", title: "角色名", width: 150, sortable: true, editor: { type: "validatebox", options: { required: true, validType: "length[1,50]" } } },
{ field: "Remark", title: "角色描述", width: 150, sortable: true, editor: { type: "textarea", options: { validType: "length[1,500]" } } },
{ field: "CreatedTime", title: "创建时间", width: 150, halign: "center", align: "center", sortable: true, formatter: function (value) { return $.osharp.tools.formatDate(value); } }
]];

  easyui 的表格验证还是不错的,比如添加一行,效果如下:

  

  向后端提交数据,这里使用 json2.js 的 JSON.stringify(data) 将数据序列化成 json 之后再提交,删除的时候提交的数据为 id 的集合,是先使用 jquery.linq.js(linq to js,能像 C# 使用 linq 一样使用 js 来操作集合数据)来提取 id 的集合,再进行序列化提交,实现如下:

 function submitAdds(objs) {
$.post("@ViewBag.AddUrl", { dtos: JSON.stringify(objs) }, ajaxResultHandler);
} function submitEdits(objs) {
$.post("@ViewBag.EditUrl", { dtos: JSON.stringify(objs) }, ajaxResultHandler);
} var deleteRows = function () {
var selectRows = grid.datagrid("getSelections");
if (selectRows.length == 0) {
$.osharp.easyui.msg.tip("请先选中要删除的行。");
return;
}
var ids = $.Enumerable.From(selectRows).Select(function (m) { return m.Id; }).ToArray();
$.osharp.easyui.msg.confirm("是否要删除所有选中的行?此操作是不可恢复的。", null, function () {
$.post("@ViewBag.DeleteUrl", { ids: JSON.stringify(ids) }, ajaxResultHandler);
});
}; function ajaxResultHandler(data) {
if (data.Type == "Success") {
grid.datagrid("reload");
}
if (data.Type == "Error") {
$.osharp.easyui.msg.error(data.Content);
} else {
$.osharp.easyui.msg.tip(data.Content);
}
}

后端部分

  后端接收到的数据为JSON字符串,需要解析成Dto,才能进行业务处理,定义了一个JsonBinder类来专门解析前端传来的JSON数据:

 /// <summary>
/// JSON数据绑定类
/// </summary>
public class JsonBinder<T> : IModelBinder
{
/// <summary>
/// 使用指定的控制器上下文和绑定上下文将模型绑定到一个值。
/// </summary>
/// <returns>
/// 绑定值。
/// </returns>
/// <param name="controllerContext">控制器上下文。</param><param name="bindingContext">绑定上下文。</param>
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
string json = controllerContext.HttpContext.Request.Form[bindingContext.ModelName];
if (string.IsNullOrEmpty(json))
{
json = controllerContext.HttpContext.Request.QueryString[bindingContext.ModelName];
}
if (string.IsNullOrEmpty(json))
{
return null;
}
JsonSerializer serializer = new JsonSerializer();
if (json.StartsWith("{") && json.EndsWith("}"))
{
JObject jsonBody = JObject.Parse(json);
object result = serializer.Deserialize(jsonBody.CreateReader(), typeof(T));
return result;
}
if (json.StartsWith("[") && json.EndsWith("]"))
{
List<T> list = new List<T>();
JArray jsonArray = JArray.Parse(json);
if (jsonArray != null)
{
list.AddRange(jsonArray.Select(jobj => serializer.Deserialize(jobj.CreateReader(), typeof(T))).Select(obj => (T)obj));
}
return list;
}
return null;
}
}

  后台处理代码如下,这里还没有进行真正的业务逻辑处理,只是简单的返回一个结果:

 [HttpPost]
[AjaxOnly]
public ActionResult Add([ModelBinder(typeof(JsonBinder<RoleDto>))] ICollection<RoleDto> dtos)
{
string[] names = dtos.Select(m => m.Name).ToArray();
AjaxResult result = new AjaxResult("角色“{0}”新增成功".FormatWith(names.ExpandAndToString()), AjaxResultType.Success);
return Json(result, JsonRequestBehavior.AllowGet);
} [HttpPost]
[AjaxOnly]
public ActionResult Edit([ModelBinder(typeof(JsonBinder<RoleDto>))] ICollection<RoleDto> dtos)
{
string[] names = dtos.Select(m => m.Name).ToArray();
AjaxResult result = new AjaxResult("角色“{0}”新增成功".FormatWith(names.ExpandAndToString()), AjaxResultType.Success);
return Json(result, JsonRequestBehavior.AllowGet);
} [HttpPost]
[AjaxOnly]
public ActionResult Delete([ModelBinder(typeof(JsonBinder<int>))] ICollection<int> ids)
{
AjaxResult result = new AjaxResult("{0} 个角色删除成功".FormatWith(ids.Count), AjaxResultType.Success);
return Json(result, JsonRequestBehavior.AllowGet);
}

  返回的AjaxResult是一个专用封装于AJAX操作结果的类型:

 /// <summary>
/// 表示Ajax操作结果
/// </summary>
public class AjaxResult
{
/// <summary>
/// 初始化一个<see cref="AjaxResult"/>类型的新实例
/// </summary>
public AjaxResult(string content, AjaxResultType type = AjaxResultType.Info, object data = null)
: this(content, data, type)
{ } /// <summary>
/// 初始化一个<see cref="AjaxResult"/>类型的新实例
/// </summary>
public AjaxResult(string content, object data, AjaxResultType type = AjaxResultType.Info)
{
Type = type.ToString();
Content = content;
Data = data;
} /// <summary>
/// 获取 Ajax操作结果类型
/// </summary>
public string Type { get; private set; } /// <summary>
/// 获取 消息内容
/// </summary>
public string Content { get; private set; } /// <summary>
/// 获取 返回数据
/// </summary>
public object Data { get; private set; }
}

  操作结果,成功返回结果,测试通过:

  

  至此,EasyUI的界面搭建基本完成,后面的文章中我们将使用这个界面构建一个会员系统,欢迎关注。

开源说明

github.com

  OSharp项目已在github.com上开源,地址为:https://github.com/i66soft/osharp,欢迎阅读代码,欢迎 Fork,如果您认同 OSharp 项目的思想,欢迎参与 OSharp 项目的开发。

  在Visual Studio 2013中,可直接获取 OSharp 的最新源代码,获取方式如下,地址为:https://github.com/i66soft/osharp.git

  

nuget

  OSharp的相关类库已经发布到nuget上,欢迎试用,直接在nuget上搜索 “osharp” 关键字即可找到
  

系列导航

本文已同步到系列目录:OSharp快速开发框架解说系列

【开源】OSharp框架解说系列(2.2):EasyUI复杂布局及数据操作的更多相关文章

  1. 【开源】OSharp框架解说系列(5.2):EntityFramework数据层实现

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

  2. 【开源】OSharp框架解说系列(5.1):EntityFramework数据层设计

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

  3. 【开源】OSharp框架解说系列(1):总体设计及系列导航

    系列文章导航 [开源]OSharp框架解说系列(1):总体设计 [开源]OSharp框架解说系列(2.1):EasyUI的后台界面搭建及极致重构 [开源]OSharp框架解说系列(2.2):EasyU ...

  4. 【开源】OSharp框架解说系列(2.1):EasyUI的后台界面搭建及极致重构

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

  5. 【开源】OSharp框架解说系列(6.1):日志系统设计

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

  6. 【开源】OSharp框架解说系列(4):架构分层及IoC

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

  7. 【开源】OSharp框架解说系列(3):扩展方法

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

  8. 【开源】OSharp3.0框架解说系列(6.2):操作日志与数据日志

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

  9. 【开源】OSharp3.0框架解说系列:新版本说明及新功能规划预览

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

随机推荐

  1. 【逆向篇】分析一段简单的ShellCode——从TEB到函数地址获取

    其实分在逆向篇不太合适,因为并没有逆向什么程序. 在http://www.exploit-db.com/exploits/28996/上看到这么一段最简单的ShellCode,其中的技术也是比较常见的 ...

  2. 获取img的真实宽高

    之前项目后台上传图片时需要对图片的宽高做限制,一开始百度了之后使用js进行判断,可是这种方式存在一定问题,后来就改在后台判断了.现在吧这两种方式都贴出来. 一.用js获取: 先说第一个方法:obj.s ...

  3. view的滑动冲突解决方案

    一.常见的滑动冲突场景 1.外部滑动方向和内部滑动方向不一致 2.外部滑动方向和内部滑动方向一致 3.上面两种情况的嵌套 二.滑动冲突处理的原则 场景1的处理原则是:当用户左右滑动时,需要让外部的vi ...

  4. 关于UIAlertAction如何修改sheet上的字体颜色

    相信很多程序员都会遇到需求是这样的: 但是你发现无论怎么设置cancel和Destructive都无法让红色字体移动到下面取消按钮上: 其实之前一直用错,用了ios9之前的UIActionSheet这 ...

  5. (转)Eclipse和MyEclipse安装和使用git(egit)图解笔记

    Eclipse.MyEclipse使用git插件(egit)图解 (转)原文来自:http://www.xuebuyuan.com/446322.html 在开发Java.JavaEE等相关程序时,我 ...

  6. “我爱背单词”beta版发布与使用说明

    我爱背单词BETA版本发布 第二轮迭代终于画上圆满句号,我们的“我爱背单词”beta版本已经发布. Beta版本说明 项目名称 我爱背单词 版本 Beta版 团队名称 北京航空航天大学计算机学院  拒 ...

  7. java身份证验证

    import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; impor ...

  8. CYQ.Data V5 分布式缓存MemCached应用开发介绍

    前言 今天大伙还在热议关于.NET Core的东西,我只想说一句:在.NET 跨平台叫了这么多年间,其实人们期待的是一个知名的跨平台案例,而不是一堆能跨平台的消息. 好,回头说说框架: 在框架完成数据 ...

  9. [转] Agile Software Development 敏捷软件开发

    原文作者:kkun 原文地址:http://www.cnblogs.com/kkun/archive/2011/07/06/agile_software_development.html 敏捷是什么 ...

  10. Linux下的.NET之旅:第一站,CentOS+Mono+Xsp构建最简单的ASP.NET服务器

    一.Mono产生的背景 由于Linux/Unix等有更强的安全性.运行效率高.拥有大量优秀的开源组件,而.Net则有着其他语言无与伦比的开发效率,因此在非微软平台下运行.Net程序的需求很强烈.Mon ...