用MVC做WinForm客户端
来源:互联网 发布:网络维修 杭州 编辑:程序博客网 时间:2024/05/20 16:13
昨天突然脑洞大开,觉得WinForm客户端也可以做成MVC!想到就做!于是把以前做的一个WinForm工程拉出来,选了角色权限模块先试个水。
第一步:调整项目结构,调整后结构如下图:
第二步:拆分逻辑
原来整个窗体类里面包含了很多业务逻辑,这部分不用说,直接拆分到Controller里面,还有工具栏点击事件的处理逻辑,也同样分离出来放到Controller里面。拆分之后,窗体类就变成了一个纯粹的View了。至于Model,就是拖进一个叫Model的文件夹里面就好了。
第三步:处理命名空间变化带来的一系列问题。大概花了两小时,部分重构完成,程序运行正常!
总结:重构后逻辑更加清晰,任务更容易分解,也更容易进行单元测试。这个思路个人认为值得推广。
部分代码:
Manager:
using System;using System.Collections.Generic;using System.Linq;using DevExpress.XtraBars;using DevExpress.XtraGrid.Views.Base;using DevExpress.XtraTreeList;using Insight.WS.Client.Base.Role.Controller;using Insight.WS.Client.Base.Role.Model;using Insight.WS.Client.Common;namespace Insight.WS.Client.Base.Role.View{ public partial class Manager : MdiBase { #region 变量声明 public static List<RoleInfo> Roles; public static RoleInfo Role; private bool First = true; #endregion #region 构造函数 public Manager() { InitializeComponent(); // 注册事件 gdvRole.FocusedRowObjectChanged += gdvRole_FocusedRowObjectChanged; treMember.CustomDrawNodeImages += CustomDrawNodeImages; treModule.CustomDrawNodeImages += DrawNodeImages; treAction.CustomDrawNodeImages += DrawNodeImages; treData.CustomDrawNodeImages += DrawNodeImages; } #endregion #region 界面事件处理 /// <summary> /// 窗体加载时初始化控件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void RoleManage_Load(object sender, EventArgs e) { InitToolBar(); Roles = new List<RoleInfo>(); Role = new RoleInfo(); // 初始化角色列表 grdRole.DataSource = Roles; Format.GridFormat(gdvRole); // 初始化角色成员 treMember.SelectImageList = imgMember; treMember.DataSource = Role.Members; Format.TreeFormat(treMember); // 初始化角色成员用户 grdUser.DataSource = Role.Users; Format.GridFormat(gdvUser); // 初始化业务模块列表 treModule.SelectImageList = imgPermission; treModule.DataSource = Role.Modules; Format.TreeFormat(treModule); // 初始化操作权限列表 treAction.DataSource = Role.Actions; Format.TreeFormat(treAction); treAction.SelectImageList = imgPermission; // 初始化数据权限列表 treData.DataSource = Role.Datas; Format.TreeFormat(treData); treData.SelectImageList = imgData; } /// <summary> /// 窗体显示时加载数据 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Manager_Shown(object sender, EventArgs e) { General.InitRoleList(); grdRole.DataSource = Roles; gdvRole.MoveFirst(); } /// <summary> /// 角色列表选中行变化 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void gdvRole_FocusedRowObjectChanged(object sender, FocusedRowObjectChangedEventArgs e) { Role = (RoleInfo) gdvRole.GetFocusedRow(); var dict = new Dictionary<string, bool> { {"DeleteRole", !Role.BuiltIn}, {"AddMember", !Role.BuiltIn} }; SwitchItemStatus(dict); treMember.DataSource = Role.Members; treMember.ExpandAll(); grdUser.DataSource = Role.Users; treData.DataSource = Role.Datas; treData.ExpandToLevel(0); treData.MoveFirst(); treAction.DataSource = Role.Actions; treAction.ExpandToLevel(0); treAction.MoveFirst(); treModule.DataSource = Role.Modules; treModule.ExpandAll(); treModule.MoveFirst(); if (!First) return; tabPermission.SelectedTabPageIndex = 1; tabPermission.SelectedTabPageIndex = 0; First = false; } /// <summary> /// 切换角色成员 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void treMember_FocusedNodeChanged(object sender, FocusedNodeChangedEventArgs e) { if (treMember.FocusedNode == null) return; var canRemove = !Role.BuiltIn && (int)treMember.FocusedNode.GetValue("NodeType") != 0; var dict = new Dictionary<string, bool> { {"Remove", canRemove} }; SwitchItemStatus(dict); } /// <summary> /// 双击角色列表编辑当前所选角色 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void gdvRole_DoubleClick(object sender, EventArgs e) { var id = (Guid) gdvRole.GetFocusedDataRow()["ID"]; var edit = barManager.Items["EditRole"]; if (gdvRole.FocusedRowHandle < 0 || !edit.Enabled) return; Event.RoleEdit(true, id); } /// <summary> /// 显示角色成员的类型图标 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void CustomDrawNodeImages(object sender, CustomDrawNodeImagesEventArgs e) { if (e.Node.Level != 0) return; e.SelectImageIndex = Convert.ToInt32(e.Node.GetValue("MemberId").ToString().Substring(0, 1)); } /// <summary> /// 重绘模块功能树节点图标 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void DrawNodeImages(object sender, CustomDrawNodeImagesEventArgs e) { e.SelectImageIndex = (int)e.Node.GetValue("Type"); } /// <summary> /// 重载菜单列表 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected override void item_ItemClick(object sender, ItemClickEventArgs e) { switch (e.Item.Name) { case "Refresh": General.InitRoleList(); break; case "NewRole": Event.RoleEdit(false, Guid.Empty); gdvRole.FocusedRowHandle = gdvRole.GetRowHandle(Roles.Count - 1); break; case "EditRole": var id = (Guid)gdvRole.GetFocusedDataRow()["ID"]; Event.RoleEdit(true, id); break; case "DeleteRole": Event.RoleDelete(); gdvRole.RefreshData(); break; case "AddMember": Event.MemberAdd(); break; case "Remove": var mid = (Guid) treMember.FocusedNode.GetValue("ID"); var member = Role.Members.Single(m => m.ID == mid); Event.MemberRemove(member); treMember.RefreshDataSource(); break; } } #endregion }}
using System;using System.Windows.Forms;using Insight.WS.Client.Base.Role.Model;using Insight.WS.Client.Base.Role.View;using static Insight.WS.Client.Common.Util.Message;namespace Insight.WS.Client.Base.Role.Controller{ public class Event { #region Manager /// <summary> /// 新建/编辑当前所选角色 /// </summary> /// <param name="isEdit"></param> /// <param name="id"></param> public static void RoleEdit(bool isEdit, Guid id) { var dig = new Wizard { IsEdit = isEdit, ObjectId = id }; dig.Close(); } /// <summary> /// 删除当前所选角色 /// </summary> public static void RoleDelete() { var msg = $"您确定要删除角色【{Manager.Role.Name}】吗?\r\n角色删除后将无法恢复!"; if (ShowConfirm(msg) != DialogResult.OK) return; var result = Repository.RemoveRole(Manager.Role.ID); if (!result.Successful) { ShowError($"{result.Message}\r\n对不起,角色【{Manager.Role.Name}】删除失败!如多次删除失败,请联系管理员。"); return; } Manager.Roles.Remove(Manager.Role); } /// <summary> /// 为当前所选角色添加成员 /// </summary> public static void MemberAdd() { var dig = new Member(); dig.Close(); } /// <summary> /// 删除当前所选角色成员 /// </summary> public static void MemberRemove(RoleMember member) { var msg = $"您确定要移除角色成员【{member.Member}】吗?\r\n角色成员被移除后相应用户将失去该角色赋予的权限!"; if (ShowConfirm(msg) != DialogResult.OK) return; var result = Repository.RemoveRoleMember(member.MemberId, member.NodeType); if (!result.Successful) { ShowError($"{result.Message}\r\n对不起,角色成员【{member.Member}】移除失败!如多次移除失败,请联系管理员。"); return; } Manager.Role.Members.Remove(member); } #endregion }}
Repository:
using System;using Insight.WS.Client.Common.Entity;using static Insight.WS.Client.Common.Util.HttpHelper;using static Insight.WS.Client.Common.Util.Utils;namespace Insight.WS.Client.Base.Role.Controller{ public class Repository { /// <summary> /// 删除指定角色 /// </summary> /// <returns>JsonResult</returns> public static JsonResult RemoveRole(Guid id) { var url = BaseServer + $"r/roles/{id}"; return HttpRequest(url, "DELETE", AutherKey); } /// <summary> /// 获取所有角色 /// </summary> /// <returns>JsonResult</returns> public static JsonResult GetRoles() { var url = BaseServer + "r/roles"; return HttpRequest(url, "GET", AutherKey); } /// <summary> /// 删除指定角色成员 /// </summary> /// <param name="id">成员关系ID</param> /// <param name="type">成员类型</param> /// <returns>JsonResult</returns> public static JsonResult RemoveRoleMember(Guid id, int type) { var url = BaseServer + $"r/roles/members/{id}?type={type}"; return HttpRequest(url, "DELETE", AutherKey); } }}
0 0
- 用MVC做WinForm客户端
- 用C#做WinForm的应用程序
- 用Winform做的一个日历
- 用WebForm替换WinForm做UI
- c++用WinForm做界面的实现
- 用三层架构来做winform程序
- c++用WinForm做界面的实现
- 【WEB API项目实战干货系列】- API访问客户端(WebApiClient适用于MVC/WebForms/WinForm)(四)
- 关于socket用winform实现简单通信 大牛可绕道 初学者可以看看 我做的时候把客户端窗口隐藏了 大家可以自己改一下
- java 使用html写UI 做winform win桌面客户端程序(一)
- MVC in WinForm
- winform智能客户端
- WINFORM+Oracle客户端布署
- winform窗体做视频
- MVC用filter做权限过滤
- 用bash做个tcp客户端
- 用bash做个tcp客户端
- 用bash做个tcp客户端
- Android Out of memory on a 5200288-byte allocation.解决方法
- C++ strIcmp 字符串大小比较
- JS的匿名函数
- android中的color使用总结
- Customers Who Never Order
- 用MVC做WinForm客户端
- 【BUG】java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
- 设计师の学习网站
- jQuery插件---Validator Plugin
- 安卓图片显示的一些怪象
- 使用aardio(快手)编程
- CSRF Token介绍与应对策略
- javascript中的__proto__, prototype和constructor
- 定义变量var test与test的区别