C#WinCE程序(.NET Compact Framework 3.5)项目重构面向抽象设计
重构关注点
- 遵循开闭原则
- 面向抽象设计
- 实现设备程序端可动态配置
重构的需求
领导想省事提出需求,将现有PDA程序修改为支持PC端由电器工程师根据实际的生产流程可配置,PDA程序在读取配置文件后动态生成导航界面。然后导航绑定的是PDA程序Dll里的界面。公司的综合赋码管理系统(CMS)作为服务器端对PDA暴露WCF服务,PDA在执行扫描操作后对CMS发起请求,CMS收到请求后匹配分析PDA的请求,分析完再返回执行结果给PDA。场景就是这样一个场景,PDA扫描条码的操作分:扫描一个码,扫描两个码,扫描多个码三种。领导让写3个界面,其实这正好可以抽象一下,相当于1个界面就能搞定;于是设计了一个扫描操作的基类窗体,把扫描的基本操作写在基类里,使用模板设计模式,扫多少个码的界面继承基类重用大部分扫描的处理逻辑。主要流程是PC端通过反射获取PDA程序的Dll里的窗体类列表,外部定义好PDA要展示的功能清单序列化成为Json格式的文件,PC端使用MTP传输到PDA上,PDA读取该文件来动态生成导航界面。
重构的过程
1)定义数据传输对象
using System; using System.Linq; using System.Collections.Generic; using System.Text; namespace ehsure.Core.Data.dto { [Serializable] /// <summary> /// 主界面菜单实体类 /// </summary> public class DesignConfig { /// <summary> /// 界面宽度 /// </summary> public int Width { get; set; } /// <summary> /// 界面高度 /// </summary> public int Height { get; set; } /// <summary> /// 界面下所有控件 /// </summary> public List<ControlsConfig> ControlsList { get; set; } } }
using System; using System.Linq; using System.Collections.Generic; using System.Text; namespace ehsure.Core.Data.dto { [Serializable] /// <summary> /// 控件UI配置参数实体 /// </summary> public class ControlsConfig { /// <summary> /// 控件ID /// </summary> public string ID { get; set; } /// <summary> /// 控件显示 /// </summary> public string ShowText { get; set; } /// <summary> /// 控件宽度 /// </summary> public int ControlWidth { get; set; } /// <summary> /// 控件高度 /// </summary> public int ControlHeight { get; set; } /// <summary> /// 控件命令字 /// </summary> public string Command { get; set; } /// <summary> /// 控件要打开的界面 /// </summary> public string ForwardForm { get; set; } /// <summary> /// 位置坐标X /// </summary> public int X { get; set; } /// <summary> /// 位置坐标Y /// </summary> public int Y { get; set; } /// <summary> /// 排序号 /// </summary> public int Sort { get; set; } } }
2)重构解决方案
原来的主程序集是个exe,建立职责是UI层的程序集,建立PDA主入口程序集。
3)编码实现动态导航(使用的自定义控件来代替Button)
自定义控件MenuButton
/// <summary> /// 菜单按钮,自定义控件 /// </summary> public class MenuButton : Button { public string ActiveFlag = "※"; public string Command { get; set; } public string ForwardForm { get; set; } protected bool itemActiveFlag = false; /// <summary> /// 是否处于被选中状态 /// </summary> public bool ItemActiveFlag { get { return itemActiveFlag; } set { itemActiveFlag = value; if (value) Text = ActiveFlag + Text; else Text = Text.Replace(ActiveFlag, ""); } } private StringFormat sf; public MenuButton() { BackColor = Color.White; ForeColor = Color.Black; Height = 28; Font = new Font("微软雅黑", 14F, FontStyle.Bold); sf = new StringFormat(); sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Center; } protected override void OnGotFocus(EventArgs e) { BackColor = SystemColors.Highlight; ForeColor = Color.OrangeRed; ItemActiveFlag = true; } protected override void OnLostFocus(EventArgs e) { BackColor = Color.White; ForeColor = Color.Black; ItemActiveFlag = false; } }
导航工作区的父容器就是一个Panel,MenuButton的高度是动态计算的,宽带是匹配父容器。
public partial class ShellMainForm : Form { public ShellMainForm() { InitializeComponent(); this.Load += new EventHandler(ShellMainForm_Load); this.KeyPreview = true; this.KeyDown += new KeyEventHandler(ShellMainForm_KeyDown); } void ShellMainForm_KeyDown(object sender, KeyEventArgs e) { if (e.KeyData == Keys.F1) { using (SystemTimeSetForm frm = new SystemTimeSetForm()) { var result = frm.ShowDialog(); if (result.Equals(DialogResult.OK)) { this.statusBar.Text = DateTime.Now.ToLongDateString() + " " + DateTime.Now.DayOfWeek; } } } if (e.KeyData == Keys.F2) { using (var powerManager = new PowerManagement()) { powerManager.SetSystemPowerState(PowerManagement.SystemPowerStates.Suspend); } } } void ShellMainForm_Load(object sender, EventArgs e) { try { Cursor.Current = Cursors.WaitCursor; MaximizeBox = false; MinimizeBox = false; FormBorderStyle = FormBorderStyle.FixedSingle; this.Text = "CMS智能终端"; this.Width = Screen.PrimaryScreen.WorkingArea.Width; this.Height = Screen.PrimaryScreen.WorkingArea.Height; this.Left = 0; this.Top = 0; statusBar.Text = string.Join(" ", new string[] { "线号:" + DeviceContext.GetInstance().GetGlobalConfig().LineNum , "设备号:" + DeviceContext.GetInstance().GetGlobalConfig().DeviceNum }); TestLogin(); DriveInit(); } finally { Cursor.Current = Cursors.Default; } } /// <summary> /// 初始化系统功能列表 /// </summary> /// <param name="config"></param> void InitSystemNavigateBar(DesignConfig config) { var list = config.ControlsList.OrderByDescending(m => m.Sort); if (list.Any()) { int index = 0; //list.Reverse(); foreach (var navigateItem in list) { var btn = new MenuButton(); btn.TabIndex = index; btn.Dock = DockStyle.Top; btn.TabIndex = workareaPanel.Controls.Count; btn.Text = navigateItem.ShowText; btn.ForwardForm = navigateItem.ForwardForm; btn.Click += new EventHandler(NavigateButton_Click); btn.KeyDown += new KeyEventHandler(NavigateButton_KeyDown); workareaPanel.Controls.Add(btn); index++; } } } /// <summary> /// 响应导航按钮回车事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void NavigateButton_KeyDown(object sender, KeyEventArgs e) { if (e.KeyValue == 13) NavigateButton_Click(sender, null); } /// <summary> /// 响应导航单击事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void NavigateButton_Click(object sender, EventArgs e) { RunModuleForm((MenuButton)sender); } private void menuClose_Click(object sender, EventArgs e) { if (MessageBox.Show("确认要退出系统", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.Yes) { this.Close(); Application.Exit(); } } /// <summary> /// 动态打开模块窗体 /// </summary> /// <param name="mb">MenuButton 被点击的控件 /// mb.ForwardForm要打开的窗体类名:{命名空间+","+类名} /// mb.Command {REPLACE,DELETE...CMS脚本对应的指令名称}</param> protected void RunModuleForm(MenuButton mb) { try { if (string.IsNullOrEmpty(mb.ForwardForm)) { throw new Exception("模块或者窗体没有设定类库信息!"); } string[] tempModulesInfo = mb.ForwardForm.Split(",".ToCharArray()); Assembly asb = Assembly.Load(tempModulesInfo.FirstOrDefault()); string frmTypeName = string.Join(".", tempModulesInfo); var form = asb.GetTypes().Where(p => p.FullName.Equals(frmTypeName)).FirstOrDefault(); if (form != null) { DeviceContext.GetInstance().OperateTypeText = mb.Text.Replace(mb.ActiveFlag, ""); var frm = (System.Windows.Forms.Form)Activator.CreateInstance(form); if (!string.IsNullOrEmpty(mb.Command)) { DeviceContext.GetInstance().CurrentCommand = mb.Command; } frm.ShowDialog(); } else throw new Exception(string.Format("类名:{0}不存在!", frmTypeName)); } catch (Exception ex) { //throw ex; MessageBox.Show("错误描述:" + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1); } } /// <summary> /// 获取应用程序界面导航配置 /// </summary> /// <returns></returns> protected DesignConfig GetDesignNavigateConfig() { var list = new List<ControlsConfig>(); System.Action<DesignConfig> addDefaultItemTask = (dc) => { dc.ControlsList.Add(new ControlsConfig { ID = Guid.NewGuid().ToString().Replace("-", ""), Command = "", ForwardForm = "ehsure.Smart.FlowUI,AdminSettingForm", ShowText = "设备配置", ControlHeight = 0, ControlWidth = 0, X = 0, Y = 0, Sort = Int32.MaxValue }); }; var path = new DirectoryInfo(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)); string fileName = path.FullName + @"\Config\DesignConfig.Config"; if (!File.Exists(fileName)) { DesignConfig dc = new DesignConfig { Height = Screen.PrimaryScreen.WorkingArea.Height, Width = Screen.PrimaryScreen.WorkingArea.Width, ControlsList = list }; addDefaultItemTask.Invoke(dc); string fileContext = JsonConvert.SerializeObject(dc); using (var fs = new FileStream(fileName, FileMode.Create)) { byte[] buffer = Encoding.UTF8.GetBytes(fileContext); fs.Write(buffer, 0, buffer.Length); fs.Flush(); fs.Close(); } return dc; } else { using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { byte[] buffer = new byte[fs.Length]; fs.Read(buffer, 0, buffer.Length); string fileContext = Encoding.UTF8.GetString(buffer, 0, buffer.Length); DesignConfig dc = JsonConvert.DeserializeObject<DesignConfig>(fileContext); if (dc != null && !dc.ControlsList.Any(m => m.Sort == Int32.MaxValue)) { addDefaultItemTask.Invoke(dc); } fs.Close(); return dc; } } } /// <summary> /// 测试连接CMS /// </summary> private void TestLogin() { string outMsg; var codeInfo = new TaskDTOCode { Code = "LoginTest" }; CFDataService.SubmitToControl(codeInfo, out outMsg); } /// <summary> /// 加载驱动 /// </summary> private void DriveInit() { string dllName = ScanCache.DllType.DllName; string dllService = ScanCache.DllType.DllService; string[] file = Directory.GetFiles(Path.GetDirectoryName(Assembly.GetCallingAssembly().GetName().CodeBase) + "\\", dllName); if (file.Length == 0) { throw new Exception(ErrorMessage.ScanComponentLoadFailed); } else { Assembly assembly = Assembly.LoadFrom(file[0]); Type typeScanService = assembly.GetType(dllService); ScanCache.BaseScanDirve = (BaseScanDriveService)assembly.CreateInstance(typeScanService.FullName); ScanCache.BaseScanDirve.Init(); } } /// <summary> /// 界面排列布局时触发,初始化界面导航 /// </summary> /// <param name="e"></param> protected override void OnResize(EventArgs e) { base.OnResize(e); workareaPanel.Controls.Clear(); var config = GetDesignNavigateConfig(); if (config != null) { InitSystemNavigateBar(config); } if (workareaPanel.Controls.Count > 0 && workareaPanel.Height < Screen.PrimaryScreen.WorkingArea.Height) { foreach (Control ctrl in workareaPanel.Controls) { ctrl.Height = workareaPanel.Height / workareaPanel.Controls.Count - 2; } workareaPanel.Controls[workareaPanel.Controls.Count - 1].Focus(); } } }
4)UI层业务窗体的实现是本篇随笔的重点
重点考量的地方就是前面所说的要面向抽象设计,封装和继承。
所有业务窗体的基类
/// <summary> /// 窗体基类 /// </summary> public partial class BaseForm : Form { private bool isScaleDown = true; /// <summary> /// 是否屏幕自适应 /// </summary> public bool IsScaleDown { get { return isScaleDown; } set { isScaleDown = value; } } private bool enterToTab = false; /// <summary> /// 是否回车变Tab /// </summary> public bool EnterToTab { get { return enterToTab; } set { enterToTab = value; } } public BaseForm() { InitializeComponent(); KeyPreview = true; SetInterval(); } private ScannerErrorService ScannerErrorService; private ScannerErrorService getScannerErrorService() { return ScannerErrorService ?? (ScannerErrorService = new ScannerErrorService()); } protected virtual void InitMenu() { } protected override void OnActivated(EventArgs e) { CustomizeCursor.CloseCursor(); base.OnActivated(e); } protected void AddMenuItem(MainMenu mainMenu, string text, ehsure.Common.Action func) { MenuItem item = new MenuItem(); item.Text = text; item.Click += delegate(object sender, EventArgs e) { try { CustomizeCursor.ShowWaitCursor(); func(); } catch (Exception ex) { ShowMessageBoxForm(ex); } finally { CustomizeCursor.CloseCursor(); } }; mainMenu.MenuItems.Add(item); } protected void AddMenuItem(MainMenu mainMenu, string mainText, string text, ehsure.Common.Action func) { MenuItem mi = null; Menu.MenuItemCollection collection = mainMenu.MenuItems; for (int i = 0; i < collection.Count; i++) { MenuItem item = collection[i]; if (string.Equals(item.Text, mainText, StringComparison.OrdinalIgnoreCase)) { mi = item; continue; } } if (mi == null) { mi = new MenuItem(); mi.Text = mainText; mainMenu.MenuItems.Add(mi); } MenuItem sub = new MenuItem(); sub.Text = text; sub.Click += delegate(object sender, EventArgs e) { try { CustomizeCursor.ShowWaitCursor(); func(); } catch (Exception ex) { ShowMessageBoxForm(ex); } finally { CustomizeCursor.CloseCursor(); } }; mi.MenuItems.Add(sub); } protected virtual void FireAction(ehsure.Common.Action action) { try { CustomizeCursor.ShowWaitCursor(); action(); } catch (Exception ex) { ShowMessageBoxForm(ex); } finally { CustomizeCursor.CloseCursor(); } } public virtual void FireActionCode(ActionCode action, string code, int inputType) { try { CustomizeCursor.ShowWaitCursor(); action(code, inputType); } catch (Exception ex) { ShowMessageBoxForm(ex); } finally { CustomizeCursor.CloseCursor(); } } private void BaseForm_Load(object sender, EventArgs e) { InitMenu(); } public void ShowMessageBoxForm(Exception ex) { CustomizeCursor.CloseCursor(); try { string msg = null; msg = ex.Message; string type = ex.GetType().FullName; if (type == "System.Net.WebException") { msg = "网络异常!"; } if (type != "System.Exception" || msg == ErrorMessage.ScanComponentLoadFailed) { ScannerErrorReport error = new ScannerErrorReport() { Id = Guid.NewGuid().ToString(), ErrorInfo = msg, ErrorTime = DateTime.Now, CustomerCode = ScanCache.UserContext.CorpId, CustomerName = ScanCache.UserContext.CorpName, Remark = ex.StackTrace }; getScannerErrorService().Insert(error); } MessageBoxForm form = new MessageBoxForm(); form.ShowMessage(msg); form.ShowDialog(); } catch (Exception eex) { MessageBoxForm form = new MessageBoxForm(); form.ShowMessage(eex.Message); form.ShowDialog(); } } private void SetInterval() { var file = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase) + "\\App.Config"; XmlDocument doc = new XmlDocument(); if (!File.Exists(file)) { ScanCache.SuccessInterval = 200; ScanCache.ErrorInterval = 3000; return; } doc.Load(file); XmlNodeList nodes = doc.GetElementsByTagName("add"); for (int i = 0; i < nodes.Count; i++) { XmlAttribute att = nodes[i].Attributes["key"]; if (att != null) { if (att.Value == "SuccessInterval") { att = nodes[i].Attributes["value"]; ScanCache.SuccessInterval = Convert.ToInt32(att.Value); } if (att.Value == "ErrorInterval") { att = nodes[i].Attributes["value"]; ScanCache.ErrorInterval = Convert.ToInt32(att.Value); } } } } private void BaseForm_Closed(object sender, EventArgs e) { if (DeviceContext.GetInstance().BarcodeData == null) { DeviceContext.GetInstance().CurrentCommand = string.Empty; DeviceContext.GetInstance().OperateTypeText = string.Empty; } this.Close(); } /// <summary> /// 屏幕自适应 /// </summary> /// <param name="frm"></param> private void ScaleDown() { int scrWidth = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width; int scrHeight = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height; if (scrWidth < this.Width) foreach (System.Windows.Forms.Control cntrl in this.Controls) { cntrl.Width = ((cntrl.Width) * (scrWidth)) / (this.Width); cntrl.Left = ((cntrl.Left) * (scrWidth)) / (this.Width); } if (scrHeight < this.Height) foreach (System.Windows.Forms.Control cntrl in this.Controls) { cntrl.Height = ((cntrl.Height) * (scrHeight)) / (this.Height); cntrl.Top = ((cntrl.Top) * (scrHeight)) / (this.Height); } } /// <summary> /// 递归控件 外接事件Enter变Tab /// </summary> /// <param name="ctrl"></param> void SetControlEnterToTab(Control ctrl) { foreach (Control subControl in ctrl.Controls) { if (subControl is TextBox || subControl is DateTimePicker || subControl is ComboBox || subControl is NumericUpDown) { subControl.KeyDown += new KeyEventHandler(ctrl_KeyDown); } if (ctrl.Controls.Count > 0) SetControlEnterToTab(subControl); } } void ctrl_KeyDown(object sender, KeyEventArgs e) { if (e.KeyValue == 13) { var ctrl = sender as Control; if (!string.IsNullOrEmpty(ctrl.Text) && ctrl is TextBox) { var tbx = ctrl as TextBox; tbx.SelectAll(); } WinceApi.keybd_event(9, 0, 0, 0); } } protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); if (e.KeyValue == 27) this.Close(); } protected override void OnLoad(EventArgs e) { if (IsScaleDown) ScaleDown(); if (EnterToTab) SetControlEnterToTab(this); this.Width = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width; this.Height = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height; base.OnLoad(e); } }
扫描业务的基类
/// <summary> /// 扫描窗体基类 /// </summary> public partial class ScanBaseForm : BaseForm { /// <summary> /// 操作类型 /// </summary> public string ScanOperateType { get { return lbOperType.Text.Trim(); } set { lbOperType.Text = value; } } /// <summary> /// 需要扫码个数 /// </summary> public int ScanBarcodeNumber { get { return int.Parse(lbCount.Text.Trim()); } set { lbCount.Text = value.ToString(); } } protected TaskDTOCode _TaskDTOCode = new TaskDTOCode(); protected string _SplitChars = string.Empty; protected string _GroupSplitFlag = string.Empty; /// <summary> /// 需要扫码的个数 /// </summary> protected int _NeedScanNumber = 0; /// <summary> /// 已经扫描的码 /// </summary> protected List<string> _BarcodeList = new List<string>(); protected Socket pdaClientSocket = null; public ScanBaseForm() { InitializeComponent(); MaximizeBox = false; MinimizeBox = false; Load += new EventHandler(ScanBaseForm_Load); } #region 扫描处理部分 public delegate void ActingThread(string code, int inputType); /// <summary> /// 窗体激活时启动扫描头,绑定事件 /// </summary> /// <param name="e"></param> protected override void OnActivated(EventArgs e) { base.OnActivated(e); ScanCache.BaseScanHandle = new BaseScanHandle(ScanCodeEventHandle); ScanCache.BaseScanDirve.CodeReaded += ScanCache.BaseScanHandle; ScanCache.BaseScanDirve.BeginScan(); tbMessage.Text = "扫描头已经打开,请扫描!"; } /// <summary> /// 读取截取字符和多码分隔符 /// </summary> protected virtual void GetGlobalConfig() { string configPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) + "\\Config\\Device.Config"; if (File.Exists(configPath)) { using (System.Data.DataSet ds = new System.Data.DataSet()) { ds.ReadXml(configPath); if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0) { var dt = ds.Tables[0]; _SplitChars = dt.Rows[0]["CodeSplit"] == null ? string.Empty : dt.Rows[0]["SplitChars"].ToString(); _GroupSplitFlag = dt.Rows[0]["CodeSplit"] == null ? string.Empty : dt.Rows[0]["CodeSplit"].ToString(); } } } } /// <summary> /// 截取正确的条码内容 /// </summary> /// <param name="scanData"></param> /// <returns></returns> protected virtual string ScanCodeToRightCode(string scanData) { if (!string.IsNullOrEmpty(_SplitChars) && string.IsNullOrEmpty(scanData)) { string[] temp = scanData.Split(_SplitChars.ToCharArray()); if (temp.Length > 1) return temp.LastOrDefault(); } return scanData; } /// <summary> /// 扫到码事件触发 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ScanCodeEventHandle(object sender, BaseScanEventArgs e) { ActingThread act = new ActingThread(ScanActionExecute); this.BeginInvoke(act, new object[] { e.Message, 1 }); } /// <summary> ///扫描到条码本地窗体处理 /// </summary> /// <param name="code"></param> /// <param name="inputType"></param> protected virtual void ScanActionExecute(string code, int inputType) { string barcode = ScanCodeToRightCode(code); if (!_BarcodeList.Contains(barcode)) { _BarcodeList.Add(barcode); tbMessage.Text = string.Format("扫描到条码:{0}", barcode); if (_NeedScanNumber < 10) { int index = _BarcodeList.Count; listView.Items[index - 1].SubItems[0].Text = index.ToString() + "-->"; listView.Items[index - 1].SubItems[1].Text = barcode; listView.Refresh(); } else { int index = _BarcodeList.Count; var li = listView.Items.Add(new ListViewItem(index.ToString())); li.SubItems[0].Text = index.ToString(); li.SubItems.Add(barcode); } } else { new MessageBoxForm().ErrorBeep(); tbMessage.ForeColor = Color.Red; tbMessage.Text = "重复扫描!"; } if (_BarcodeList.Count == _NeedScanNumber) { FireAction(SendRequest); } //选中刚刚扫描到的码 foreach (ListViewItem item in listView.Items) { if (item.SubItems[1].Text.Trim().Equals(_BarcodeList.LastOrDefault())) { item.Selected = true; } } listView.Focus(); } /// <summary> /// 关闭扫描头,取消绑定 /// </summary> /// <param name="e"></param> protected override void OnDeactivate(EventArgs e) { base.OnDeactivate(e); ScanCache.BaseScanDirve.CodeReaded -= ScanCache.BaseScanHandle; ScanCache.BaseScanDirve.StopScan(); } #endregion void ScanBaseForm_Load(object sender, EventArgs e) { ScanOperateType = DeviceContext.GetInstance().OperateTypeText; ScanBarcodeNumber = _NeedScanNumber; GetGlobalConfig(); if (_NeedScanNumber < 10) InitNavigateView(); else { lbCount.Text = "N(多个)"; listView.Items.Clear(); } _TaskDTOCode.ParentCode = DeviceContext.GetInstance().CurrentCommand; if (DeviceContext.GetInstance().GetGlobalConfig().IsOpenTcpClient) { pdaClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); pdaClientSocket.Connect(new IPEndPoint(IPAddress.Parse(DeviceContext.GetInstance().GetGlobalConfig().TcpClientIp), DeviceContext.GetInstance().GetGlobalConfig().TcpPort)); if (pdaClientSocket != null && pdaClientSocket.Connected) { tbMessage.Text += (Environment.NewLine + "连接TCP Server成功!"); } } } /// <summary> /// 初始化导航视图 /// </summary> public virtual void InitNavigateView() { listView.Items.Clear(); for (int i = 0; i < _NeedScanNumber; i++) { var li = listView.Items.Add(new ListViewItem((i + 1).ToString())); li.SubItems[0].Text = "1"; li.SubItems.Add("请扫描..."); } } /// <summary> /// 对CMS发起请求 eg: { Code = txt_BoxCode.Text.Trim(), EptCode = txt_BagCode.Text.Trim(), ParentCode = "EA_BOX_BAG" }; /// </summary> protected virtual void SendRequest() { tbMessage.Text += (Environment.NewLine + "正在发起请求,请等待CMS回应..."); DeviceContext.GetInstance().BarcodeData = _TaskDTOCode; if (!DeviceContext.GetInstance().GetGlobalConfig().IsOpenTcpClient) { #region WCF请求 string msgifno = ""; try { Cursor.Current = Cursors.WaitCursor; CFDataService.SubmitToControl(_TaskDTOCode, out msgifno); } catch (Exception ex) { tbMessage.Text += "CMS返回错误消息:" + ex.Message; return; } finally { Cursor.Current = Cursors.Default; } if (!string.IsNullOrEmpty(msgifno)) { tbMessage.Text += (Environment.NewLine + msgifno); } else { tbMessage.Text += "操作失败,CMS服务器端无响应!"; } #endregion } else { if (pdaClientSocket != null && !pdaClientSocket.Connected) { pdaClientSocket.Connect(new IPEndPoint(IPAddress.Parse(DeviceContext.GetInstance().GetGlobalConfig().TcpClientIp), DeviceContext.GetInstance().GetGlobalConfig().TcpPort)); } if (pdaClientSocket == null || !pdaClientSocket.Connected) { tbMessage.Text += (Environment.NewLine + "和CMS服务器端建立连接失败!"); } byte[] buffer = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(_TaskDTOCode)); try { Cursor.Current = Cursors.WaitCursor; pdaClientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None); byte[] revBuffer = new byte[1024]; int len = pdaClientSocket.Receive(revBuffer, SocketFlags.None); if (len > 0) { string resultMessage = Encoding.UTF8.GetString(revBuffer, 0, len); tbMessage.Text += (Environment.NewLine + resultMessage); } } catch (Exception ex) { tbMessage.Text += (Environment.NewLine + ex.Message); } finally { Cursor.Current = Cursors.Default; } } } private void menuItem2_Click(object sender, EventArgs e) { Close(); } private void menuItem1_Click(object sender, EventArgs e) { if (_BarcodeList.Count != _NeedScanNumber && _NeedScanNumber < 10) { tbMessage.Text += (Environment.NewLine + "扫描条码个数不正确!"); return; } FireAction(SendRequest); } private void menuItem3_Click(object sender, EventArgs e) { if (_BarcodeList.Count > 0) { tbMessage.Text = "已清空,请开始扫描!"; _BarcodeList.Clear(); int index = 0; foreach (ListViewItem item in listView.Items) { index++; item.SubItems[0].Text = index.ToString(); item.SubItems[1].Text = "请扫描..."; } listView.Refresh(); } else { new MessageBoxForm().ErrorBeep(); tbMessage.Text = "已扫编码数量为0,请开始扫描!"; } } }
具体子类是实现,只是需要几行代码。
[ModuleDescription("外部可调用","扫1个码进行操作,适用于整箱删除,查关联关系等操作。")] public partial class ScanOneForm : ScanBaseForm { public ScanOneForm() { InitializeComponent(); _NeedScanNumber = 1; Menu = mainMenu2; } protected override void SendRequest() { _TaskDTOCode.Code = _BarcodeList.FirstOrDefault(); _TaskDTOCode.EptCode = ""; base.SendRequest(); } }
[ModuleDescription("外部可调用","扫两个码进行操作,适用于比如单品替换,添加到箱等操作。")] public partial class ScanTwoForm : ScanBaseForm { public ScanTwoForm() { InitializeComponent(); _NeedScanNumber = 2; Menu = mainMenu2; } protected override void SendRequest() { _TaskDTOCode.Code = _BarcodeList.FirstOrDefault(); _TaskDTOCode.EptCode = _BarcodeList.LastOrDefault(); base.SendRequest(); } }
[ModuleDescription("外部可调用","扫N个码进行操作,适用批量处理等操作。码之间用分隔符连接,N指的是大于10的情况。")] public partial class ScanNForm : ScanBaseForm { public ScanNForm() { InitializeComponent(); _NeedScanNumber = 11; Menu = mainMenu2; } protected override void SendRequest() { _TaskDTOCode.Code = string.Join(_GroupSplitFlag, _BarcodeList.ToArray()); _TaskDTOCode.EptCode = ""; base.SendRequest(); } }
重构的心得
又是一次认真思考过后的编程实践。总之,不是为了完成任务而编码。
重构的成果
这样的文章只是适合自己记录一下,编码心得,思路。对外人好像也没啥用吧。只是觉得好久不写博客,练习一下。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
"作者:" 数据酷软件工作室
"出处:" http://datacool.cnblogs.com
"专注于CMS(综合赋码系统),MES,WCS(智能仓储设备控制系统),WMS,商超,桑拿、餐饮、客房、足浴等行业收银系统的开发,15年+从业经验。因为专业,所以出色。"
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
"作者:" 数据酷软件工作室
"出处:" http://datacool.cnblogs.com
"专注于CMS(综合赋码系统),MES,WCS(智能仓储设备控制系统),WMS,商超,桑拿、餐饮、客房、足浴等行业收银系统的开发,15年+从业经验。因为专业,所以出色。"
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++