C# Winform下一個熱插拔的MIS/MRP/ERP框架13(窗體基類)
阿新 • • 發佈:2018-11-10
作為一個ERP資料處理框架,大部分的開發場景都差不多。
理想中,對於通用資料處理,我的步驟如下:
1、為窗體指定資料來源(資料表/查詢等);
2、拖入編輯控制元件,指定繫結欄位;
3、結束。
為此,我設計了幾個基類窗體,給它們分成幾個場景(如無資料/單表資料/主從表/多表關聯等),在不同的業務模型下,我選取相應的基類窗體進行繼承。
首先,看看最基礎的基類窗體,它包含了基礎的處理(諸如多語言載入、許可權判斷、狀態重新整理、自動資料繫結等基礎方法和屬性):
/// <summary> /// 窗體基類 /// </summary> publicpartial class Fm11Base : Form { //private:只能在本類中使用 //protected:在本類中及其子類中可以使用 //internal:同一名稱空間(程式集)中的類可以使用 //public:所有類均可使用 /// <summary> /// 用於耗時任務展示任務執行狀態 /// </summary> protected Fm11BgwkStatus fm11BgwkStatus; [Description("窗體除基本狀態控制查改刪外,是否跳過其它許可權控制.為是的情況下,所有許可權判定都將為真."), DefaultValue(false), Browsable(true)] public bool IgnoreRightsControl { get; set; } /// <summary> /// <para>指定當前繫結的資料來源.在獲取資料來源後並繫結後記錄一個標記值,用於一個窗體多個繫結源時區分當前所繫結的資料來源.</para> /// 單個繫結源可在FormOnload時繫結一次,無需設定/// </summary> public BindingSource CurBindingSource { get; set; } /// <summary> /// <para>指定已經繫結過的資料來源名稱,避免重複繫結</para> /// 一般只有一個BSMaster,當存在多個時,以A,B,C方式存入. /// </summary> public List<string> HasBindBSNames { get; set; } = new List<string>(); /// <summary> /// 窗體當前繫結的主要資料來源的新增/編輯位置(當記錄進入新增和編輯狀態時,需寫入此值;當瀏覽到其它記錄以便複製貼上時,可以利用此狀態) /// </summary> public int CurBSEditPos = -1; /// <summary> /// 窗體當前繫結的主要資料來源的當前位置(不一定是編輯位置) /// </summary> public int CurBSPosition = 0; /// <summary> /// 窗體正在建立時(不是Loading),利用此標記在載入資料時不觸發CurrentChange事件 /// </summary> public bool OnIniting = false; /// <summary> /// 編輯狀態標記:0-瀏覽,1-新增,2-編輯 /// </summary> [Description("編輯狀態標記:0-瀏覽,1-新增,2-編輯"), Browsable(false)] public int EditStatus; /// <summary> /// 從物件列表中定義的載入引數,窗體載入時提供.主要用於同一個窗體在不同模組載入時根據此引數進行資料過濾.如果許可權窗體,不同模組點開則由只顯示指定模組的資料. /// </summary> [Description("窗體載入時提供的引數,主要用於同一個窗體在不同模組載入時根據此引數進行資料過濾.如果許可權窗體,不同模組點開則由只顯示指定模組的資料."), Browsable(true)] public string OnLoadParams { get; set; } /// <summary> /// 當前使用者開啟窗體後帶入的許可權列表 /// </summary> [Description("當前使用者開啟窗體後帶入的許可權列表"), Browsable(false)] public string RightsList; /// <summary> /// 預設將ENTER鍵動作轉為TAB /// </summary> public bool EnterToTAB = true; /// <summary> /// 顯示模式:0為帳戶ID;1為姓名;2為使用者全名; 3為使用者名稱 - 姓名;4為使用者名稱 - 全名; /// </summary> protected internal int UserNameDispType = 4; /// <summary> /// 所有窗體的基類,可以設定多語言等通用功能 /// </summary> public Fm11Base() { OnIniting = true; InitializeComponent(); } /// <summary> /// 按指定的鍵值直接定位到某條記錄 /// </summary> /// <param name="tagBS">指定BS,有可能是定位其它資料來源而非主資料</param> /// <param name="tagDT">必須指定DT,與BS匹配,除直接DT外,有可能是Dataset的某一Table或關聯表的連線</param> /// <param name="keyFieldName">欄位名稱</param> /// <param name="pKeyValue">欄位值</param> public virtual void GotoRecord(BindingSource tagBS, DataTable tagDT, string keyFieldName, object pKeyValue) { if (tagBS == null) { MyMsg.Warning("資料來源未完成初始化,無法定位."); return; } if (EditStatus != 0) { MyMsg.Warning("窗體正在編輯中,無法定位."); return; } HpDataTable.GotoRecord(tagBS, tagDT, keyFieldName, pKeyValue); } /// <summary> /// 設定當前窗體的狀態列標籤(名稱需指定為:LabStsMain)字串(不是主框架的狀態列字元); /// 輸入..將預設顯示(等待指令...) /// </summary> /// <param name="statusText"></param> protected void SetMainStatus(string statusText) { object o = GetObjInstance("LabStsMain"); if (o == null) o = GetObjInstance("StsLabMain"); if (o != null) { if (statusText == "..") statusText = MultiLang.Surface(null, "Waitting", "", true); ((ToolStripStatusLabel)o).Text = statusText; Refresh(); } else { MyMsg.Exclamation("The status label does not exist."); return; } } private void Fm11Base_FormClosing(object sender, FormClosingEventArgs e) { if (EditStatus > 0) { if (e.CloseReason == CloseReason.UserClosing || e.CloseReason == CloseReason.FormOwnerClosing || e.CloseReason == CloseReason.None) { if (MyMsg.Question("當前窗體正處於"+(EditStatus==1?"新增":"編輯")+"狀態,確定要繼續關閉嗎?") == DialogResult.No) { e.Cancel = true; } } } } /// <summary> /// 獲取當前的活動控制元件 /// </summary> /// <returns></returns> protected Control GetActiveControl() { Control activeControl = this.ActiveControl; while ((activeControl as ContainerControl) != null) { activeControl = (activeControl as ContainerControl).ActiveControl; } return activeControl; } /// <summary> /// 截獲系統訊息 /// </summary> /// <param name="msg"></param> /// <param name="keyData"></param> /// <returns></returns> protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { Control actControl = GetActiveControl(); if ((keyData == Keys.Enter) && (EnterToTAB == true) && !(actControl is Button)) { Type mtype = actControl.GetType(); if (mtype.GetProperty("AcceptsReturn") != null) { bool acptRtn =OString.NZ2Bool(mtype.GetProperty("AcceptsReturn").GetValue(actControl, null)); if (!acptRtn) { SendKeys.Send("{TAB}"); return true; } else { return false; } } else { SendKeys.Send("{TAB}"); return true; } } else if (keyData == Keys.F12) { Control control = GetActiveControl(); if (control == null) return false; string tipStr = OString.NZ2Str(control.AccessibleDescription).Trim(); if (!string.IsNullOrEmpty(tipStr)) { if (control.Parent != null) { TtipF12.Show(tipStr, control.Parent, control.Location.X, control.Location.Y + 26, 2000); return false; } else return false; } else return false; } else { return false; } } /// <summary> /// 判斷當前使用者是否在當前窗體擁有許可權(可支援多個許可權同時判斷,以逗號分割) /// <para>同時滿足時才會返回True</para> /// </summary> /// <param name="rightCodes">add,open等許可權碼,不區分大小寫</param> /// <returns></returns> protected bool HasRights(string rightCodes) { if (IgnoreRightsControl || (GlbInfo.User.IsAdmin)) return true; if (OString.ListInListNeedAll(rightCodes, RightsList,",",true)) { return true; } else return false; } /// <summary> /// 判斷當前使用者是否在指定的業務角色中(可支援多個角色同時判斷,以逗號分割) /// <para>同時滿足時才會返回True</para> /// </summary> /// <param name="roleRKEYs">{DEV}開發者,{ALL}全體等角色RKEY,不區分大小寫</param> /// <returns></returns> protected bool HasRolesBusi(string roleRKEYs) { if (OString.ListInListNeedAll(roleRKEYs, GlbInfo.User.RolesUserIDS,",",true)) { return true; } else return false; } /// <summary> /// 設定控制元件的屬性值(無此屬性或設定出錯則返回FALSE) /// </summary> /// <param name="targetControl">目標控制元件</param> /// <param name="PropName">區分大小寫</param> /// <param name="setValue">寫入值</param> /// <returns></returns> public bool BaseSetControlProp(Control targetControl, string PropName, object setValue) { try { Type type = targetControl.GetType(); PropertyInfo per = type.GetProperty(PropName); if (per != null) { per.SetValue(targetControl, setValue, null); return true; } return false; } catch (Exception) { return false; } } /// <summary> /// 設定控制元件的屬性值(無此屬性或設定出錯則返回FALSE) /// </summary> /// <param name="targetObject"></param> /// <param name="PropName"></param> /// <param name="setValue"></param> /// <returns></returns> public bool BaseSetObjectProp(object targetObject, string PropName, object setValue) { try { Type type = targetObject.GetType(); PropertyInfo per = type.GetProperty(PropName); if (per != null) { per.SetValue(targetObject, setValue, null); return true; } return false; } catch (Exception) { return false; } } /// <summary> /// 清空控制元件中的子控制元件值(有Value屬性的會先設定Value,其他設定Text) /// </summary> /// <param name="targetControl">目標控制元件,如PANEL</param> /// <param name="expChildNames">要排除的子控制元件名稱,以(,)號分隔.</param> public void BaseClearControl(Control targetControl, string expChildNames = "") { if (targetControl.Controls.Count > 0) { foreach (Control ctl in targetControl.Controls) { if (string.IsNullOrEmpty(expChildNames) || (("," + expChildNames + ",").IndexOf("," + ctl.Name + ",") < 0)) {//沒有指定過濾控制元件或者當前控制元件不是指定過濾控制元件 if (!(ctl is Label) && !(ctl is Button)) { if (!BaseSetControlProp(ctl, "Value", null)) { BaseSetControlProp(ctl, "Text", null); } } } } } } /// <summary> /// 將指定控制元件的所有子控制元件設定為只讀(無ReadOnly及JmReadOnly屬性的設定Enabled) /// </summary> /// <param name="targetControl">目標控制元件</param> /// <param name="readOnly">是否只讀</param> protected void BaseSetControlReadonly(Control targetControl, bool readOnly) { if (targetControl.Controls.Count > 0) { foreach (Control ctl in targetControl.Controls) { if (BaseSetControlProp(ctl, "ReadOnly", readOnly)) { BaseSetControlProp(ctl, "Enabled", true); } else { if (BaseSetControlProp(ctl, "JmReadOnly", readOnly)) { BaseSetControlProp(ctl, "Enabled", true); } else { //如果無ReadOnly及JmReadOnly屬性,並且此控制元件沒有子控制元件(如Panel下有子控制元件,則不能設定Panel為無效,而應該設定其子控制元件),則設定Enabled屬性. if (ctl.Controls.Count < 1) { BaseSetControlProp(ctl, "Enabled", !readOnly); } else { BaseSetControlReadonly(ctl, readOnly); } } } } } else { if (BaseSetControlProp(targetControl, "ReadOnly", readOnly)) {//成功設定了只讀,放開Enabled屬性 BaseSetControlProp(targetControl, "Enabled", true); } } } /// <summary> /// 根據控制元件名稱取得object物件 /// </summary> /// <param name="objName"></param> /// <returns></returns> protected object GetObjInstance(string objName) { try { object o = this.GetType().GetField(objName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase).GetValue(this); return o; } catch (Exception) { return null; } } /// <summary> /// 在某個物件內根據控制元件名稱獲取子物件 /// </summary> /// <param name="tagObject"></param> /// <param name="objName"></param> /// <returns></returns> protected object GetObjInstanceIn(object tagObject, string objName) { try { Type type = tagObject.GetType(); object o = type.GetField(objName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase).GetValue(this); return o; } catch (Exception ex) { MyMsg.Information(ex.Message); return null; } } #region 資料操作按鈕通用方法 /// <summary> /// 設定窗體中新增/編輯等符合命名規則的按鈕狀態(含許可權判斷) /// </summary> protected virtual void BaseResetCmdState() { SetObjectEnabled("CmdRcdNew", (EditStatus == 0) && HasRights("add")); SetObjectEnabled("CmdRcdBack", (CurBSEditPos >= 0) && (CurBSPosition != CurBSEditPos)); SetObjectEnabled("CmdRcdCopyNew", (EditStatus == 0) && HasRights("add")); SetObjectEnabled("CmdRcdEdit", (EditStatus == 0) && HasRights("edit")); SetObjectEnabled("CmdRcdUndo", (EditStatus > 0)); SetObjectEnabled("CmdRcdSave", (EditStatus > 0) && (HasRights("add") || HasRights("edit"))); SetObjectEnabled("CmdRcdDelete", (EditStatus == 0) && HasRights("delete")); SetObjectEnabled("CmdRcdPreview", (EditStatus == 0) && (HasRights("preview") || HasRights("print"))); SetObjectEnabled("CmdRcdPrint", (EditStatus == 0) && HasRights("print")); SetObjectEnabled("CmdRcdSync", (EditStatus == 0) && HasRights("sync")); } /// <summary> /// 設定物件(Control/ToolStripItem)是否可用 /// </summary> /// <param name="objName"></param> /// <param name="enb"></param> public void SetObjectEnabled(string objName, bool enb) { object tagO = GetObjInstance(objName); if (tagO == null) return; if (tagO is Control) { ((Control)tagO).Enabled = enb; } else if (tagO is ToolStripItem) { ((ToolStripItem)tagO).Enabled = enb; } } #endregion private void InitControlText(string ctlName,string tagText) { object o = GetObjInstance(ctlName); if (o != null) { Type mtype = o.GetType(); if (mtype.GetProperty("Text") != null) { if (mtype.GetProperty("Text").GetValue(o, null) != null) { if (!string.IsNullOrEmpty(tagText)) mtype.GetProperty("Text").SetValue(o, tagText, null); } } } } /// <summary> /// 對A12系列控制元件進行初始化作業(Datagridview中的列控制元件無法自動初始化) /// </summary> /// <param name="tagControls"></param> private void DoA12ControlInits(Control.ControlCollection tagControls) { try { foreach (Control ctc in tagControls) { if (ctc != null) { Type tmpType = ctc.GetType(); if ((!ctc.HasChildren) || OString.StrInSplitString(tmpType.Name, "A12BtnTextBox,A12ComboBox")) { if (tmpType.Name == "A12ComboBox") { MethodInfo mm = tmpType.GetMethod("DoRequery"); mm.Invoke(ctc, null); } else if (tmpType.Name == "A12BtnTextBox") { MethodInfo mm = tmpType.GetMethod("DoInitilize"); mm.Invoke(ctc, null); } } else { DoA12ControlInits(ctc.Controls); } } } } catch (Exception) { } } private void Fm11Base_Load(object sender, EventArgs e) { OnIniting = false; //載入多語言資源,設計時狀態不執行 if (!DesignMode) { InitObjectsText(this); //設定全域性固定的多語言 InitControlText("TpgDataList", MultiLang.Surface(null, "FormTabList", "", true)); InitControlText("TpgDataDetail", MultiLang.Surface(null, "FormTabDetail", "", true)); InitControlText("CmdRcdNew", MultiLang.Surface(null, "CmdRcdNew", "", true)); InitControlText("CmdRcdBack", MultiLang.Surface(null, "CmdRcdBack", "", true)); InitControlText("CmdRcdCopyNew", MultiLang.Surface(null, "CmdRcdCopyNew", "", true)); InitControlText("CmdRcdEdit", MultiLang.Surface(null, "CmdRcdEdit", "", true)); InitControlText("CmdRcdUndo", MultiLang.Surface(null, "CmdRcdUndo", "", true)); InitControlText("CmdRcdSave", MultiLang.Surface(null, "CmdRcdSave", "", true)); InitControlText("CmdRcdDelete", MultiLang.Surface(null, "CmdRcdDelete", "", true)); InitControlText("CmdRcdPreview", MultiLang.Surface(null, "CmdRcdPreview", "", true)); InitControlText("CmdRcdPrint", MultiLang.Surface(null, "CmdRcdPrint", "", true)); InitControlText("CmdRcdSync", MultiLang.Surface(null, "CmdRcdSync", "", true)); string txtRequery = MultiLang.Surface(null, "CmdRequery", "", true); InitControlText("CmdRequery01", txtRequery); InitControlText("CmdRequery02", txtRequery); InitControlText("CmdRequery03", txtRequery); InitControlText("CmdRequery04", txtRequery); InitControlText("CmdRequery05", txtRequery); string txtFilter = MultiLang.Surface(null, "LabFilter", "", true); InitControlText("LabFilter01", txtFilter); InitControlText("LabFilter02", txtFilter); InitControlText("LabFilter03", txtFilter); InitControlText("LabFilter04", txtFilter); InitControlText("LabFilter05", txtFilter); } //對A12系列控制元件進行初始化作業(如初始化下拉框控制元件資料) DoA12ControlInits(this.Controls); } /// <summary> /// 初始化當前窗體內的文字(如果設定了多語言檔案,則按多語言定義檔案顯示) /// Tooltips控制元件不支援多語言顯示 /// </summary> /// <param name="tagObj">預設為this</param> public void InitObjectsText(object tagObj) { Type curType = tagObj.GetType(); FieldInfo[] fieldInfos = curType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance); string tmpText = string.Empty; foreach (FieldInfo fi in fieldInfos) { object o = fi.GetValue(this); if (o != null) { Type objType = o.GetType(); if (objType.GetProperty("Text") != null) { tmpText = MultiLang.Surface(this, fi.Name + ".Text", string.Empty); if (!string.IsNullOrEmpty(tmpText)) objType.GetProperty("Text").SetValue(o, tmpText, null); } if (objType.GetProperty("Caption") != null) { tmpText = MultiLang.Surface(this, fi.Name + ".Caption", string.Empty); if (!string.IsNullOrEmpty(tmpText)) objType.GetProperty("Caption").SetValue(o, tmpText, null); } if (objType.GetProperty("Hint") != null) { tmpText = MultiLang.Surface(this, fi.Name + ".Hint", string.Empty); if (!string.IsNullOrEmpty(tmpText)) objType.GetProperty("Hint").SetValue(o, tmpText, null); } if (objType.GetProperty("SuperTip") != null) { tmpText = MultiLang.Surface(this, fi.Name + ".SuperTip", string.Empty); if (!string.IsNullOrEmpty(tmpText)) objType.GetProperty("SuperTip").SetValue(o, tmpText, null); } } } } private void Fm11Base_Resize(object sender, EventArgs e) { //此處避免子窗體切換時造成閃屏 if (this.IsMdiChild) { if (this.ParentForm.ActiveMdiChild == this) { this.WindowState = FormWindowState.Maximized; } else { this.WindowState = FormWindowState.Normal; } } } /// <summary> /// 根據提供的BindingSource,自動繫結窗體控制元件的資料來源(要求命名規則匹配); /// <para>首先繫結勾選框屬性(點選即更新資料來源,DBNull預設為False)</para> /// <para>再繫結Value及Text,所有繫結都預設從資料來源帶出格式驗證</para> /// 如果控制元件在Tag中指定了繫結欄位{BindingField:RKEY},則使用指定值繫結 /// </summary> /// <param name="ctc">要繫結的控制元件集合,如This.controls會查詢整個窗體控制元件,如果有明確的定義,儘量縮小範圍,如指定某個Panel或Page中的控制元件</param> /// <param name="bindingSource">不指定時將使用窗體的當前繫結的BS</param> /// <param name="bindingName">繫結名稱,避免重複繫結</param> /// <param name="bindlevel">繫結層次,此值在外部呼叫時無須變更,預設為0即可.遞迴繫結子控制元件時不會因為bindingName忽略繫結</param> protected void AutoBindDataSource(Control.ControlCollection ctc, BindingSource bindingSource = null, string bindingName = "BSMaster", int bindlevel = 0) { string stText = MultiLang.Surface(null, "BindingControlDS", "正在為控制元件繫結資料來源", true); try { //首次繫結時,如果窗體已經繫結過此資料來源,則退出.如果是下級控制元件繫結,則繼續 if ((HasBindBSNames.Contains(bindingName)) && (bindlevel == 0)) { return; } if (bindingSource == null) { if (CurBindingSource == null) { SetMainStatus(stText + "error(current bs is null)."); return; } else { bindingSource = CurBindingSource; } } SetMainStatus(stText + "..."); foreach (Control ctrl in ctc) { if (ctrl != null) { Type mtype = ctrl.GetType(); //A12BtnTxt包含子元件,是一個組合控制元件,應當成一個整體看待 if ((!ctrl.HasChildren) || (mtype.Name=="A12BtnTextBox") || (mtype.Name=="A12TextBox") || (mtype.Name == "A12ComboBox")) { string tagFieldName = string.Empty; string ctrlTagString = OString.NZ2Str(ctrl.Tag); string tagRlsControlName = OString.GetMidStr(ctrlTagString, "{UserNameLab:", "}").Trim(); //看下控制元件是否有TagBindField屬性 if (mtype.GetProperty("TagBindField") != null) { object o = mtype.GetProperty("TagBindField").GetValue(ctrl,null); if (o != null) tagFieldName = o.ToString(); } //如果沒有獲取到,則從Tag中獲取 if (string.IsNullOrEmpty(tagFieldName)) { tagFieldName = OString.GetMidStr(ctrlTagString, "{BindingField:", "}").Trim(); } //如果沒有獲取到,則從名稱中擷取 if (string.IsNullOrEmpty(tagFieldName)) { if ((ctrl.Name.IndexOf("AB") == 0) && (ctrl.Name.IndexOf("_") > 0)) { tagFieldName = ctrl.Name.Substring(ctrl.Name.IndexOf("_") + 1); } } if (!string.IsNullOrEmpty(tagFieldName)) { try { Binding TmpBinding = null; if (mtype.Name == "A12ComboBox") //自定義下拉框控制元件直接繫結Value屬性 { TmpBinding = ctrl.DataBindings.Add("Value", bindingSource, tagFieldName, true); } else if (mtype.Name == "A12BtnTextBox") { TmpBinding = ctrl.DataBindings.Add("Value", bindingSource, tagFieldName, true); } else if (ctrl is DateTimePicker) { //日期時間控制元件直接繫結Text屬性 TmpBinding = ctrl.DataBindings.Add("Text", bindingSource, tagFieldName, true,DataSourceUpdateMode.OnPropertyChanged); } else { if (mtype.GetProperty("Checked") != null) { TmpBinding = ctrl.DataBindings.Add("Checked", bindingSource, tagFieldName, true, DataSourceUpdateMode.OnPropertyChanged, 0);//當null時設定為0,不能為False,否則會出錯. } else if (mtype.GetProperty("Value") != null) { TmpBinding = ctrl.DataBindings.Add("Value", bindingSource, tagFieldName, true); } else if (mtype.GetProperty("Text") != null) { TmpBinding = ctrl.DataBindings.Add("Text", bindingSource, tagFieldName, true); } } if ((TmpBinding != null) && (!string.IsNullOrEmpty(tagRlsControlName))) { TmpBinding.BindingComplete += BaseBSBindingComplete; } } catch (Exception) { continue; } } //沒有子控制元件的處理完成直接跳到下一個控制元件,否則檢查子控制元件 continue; } else { AutoBindDataSource(ctrl.Controls, bindingSource, bindingName, 1); } //否則檢查子控制元件 } } //首次繫結才記錄此值,遞迴時下級控制元件繫結不變更 if (bindlevel == 0) HasBindBSNames.Add(bindingName); } catch (Exception ex) { SetMainStatus(stText + "error:" + ex.Message); } finally { SetMainStatus(""); } } /// <summary> /// 資料繫結互動後,對設定有{UserNameLab:的Tag屬性的控制元件,根據其值(使用者ID)關聯顯示使用者其他資訊 /// <para>{UserNameLab:Lab1}中Lab1即為顯示額外資訊的控制元件名稱</para> /// </summary> /// <param name="sender"></param> /// <param name="e">接受一個Bindingsource的BindingComplete事件</param> protected void BaseBSBindingComplete(object sender, BindingCompleteEventArgs e) { if (e.BindingCompleteState == BindingCompleteState.Success) { string ctrlTagString = OString.NZ2Str(e.Binding.Control.Tag); string tagRlControlName = OString.GetMidStr(ctrlTagString, "{UserNameLab:", "}").Trim(); if (!string.IsNullOrEmpty(tagRlControlName)) { //繫結控制元件指定了自動關聯控制元件 string userID = "system"; Type stype = e.Binding.Control.GetType(); if (stype.GetProperty("Text") != null) { userID = e.Binding.Control.Text; } object tagO = GetObjInstance(tagRlControlName); if (tagO != null) { try { string tagValue = string.Empty; if (UserNameDispType == 0) { tagValue = userID; } else { List<object> tagUser = GlbInfo.GetSysUserInfo(userID, "UserName" + GlbInfo.Language + ",FullName" + GlbInfo.Language); if (tagUser.Count > 0) { if (UserNameDispType == 1) tagValue = OString.NZ2Str(tagUser[0]); else if (UserNameDispType == 2) tagValue = OString.NZ2Str(tagUser[1]); else if (UserNameDispType == 3) tagValue = userID + " - " + OString.NZ2Str(tagUser[0]); else if (UserNameDispType == 4) tagValue = userID + " - " + OString.NZ2Str(tagUser[1]); } } Type mtype = tagO.GetType(); if (mtype.GetProperty("Value") != null) { BaseSetObjectProp(tagO, "Value", tagValue); } else if (mtype.GetProperty("Text") != null) { BaseSetObjectProp(tagO, "Text", tagValue); } } catch (Exception) { } } } } } #region 對話方塊顯示應用程式作業狀態 /// <summary> /// 指定一個耗時任務監控窗體的執行引數, 其中RunningAction = delegate () { MethordName(bgwk); } /// </summary> protected class BgwkDef { public BackgroundWorker TagBgwk; public Action RunningAction; public int TProgMinimum = 0; public int TProgStep = 1; public int TProgMaximum = 100; public string RunningStatus; } /// <summary> /// 開始一個耗時較久的任務,呼叫前須先定義一個BgwkDef /// </summary> /// <param name="sBgwkDef"></param> protected void BeginBgwork(BgwkDef sBgwkDef) { if (fm11BgwkStatus == null) { fm11BgwkStatus = new Fm11BgwkStatus(); } if (fm11BgwkStatus != null) { fm11BgwkStatus.ProgMain.Minimum = sBgwkDef.TProgMinimum; fm11BgwkStatus.ProgMain.Step = sBgwkDef.TProgStep; fm11BgwkStatus.ProgMain.Maximum = sBgwkDef.TProgMaximum; fm11BgwkStatus.TopLevel = false; fm11BgwkStatus.Parent = this; fm11BgwkStatus.Show(); fm11BgwkStatus.BringToFront(); fm11BgwkStatus.Left = (this.Width - fm11BgwkStatus.Width) / 2; fm11BgwkStatus.Top = (this.Height - fm11BgwkStatus.Height) / 2 - 90; } if (sBgwkDef.RunningAction == null) { MyMsg.Warning("系統後臺任務必須指定作業方法,請檢查!"); return; } BackgroundWorker tagBgwk = sBgwkDef.TagBgwk ?? new BackgroundWorker(); tagBgwk.WorkerSupportsCancellation = true; tagBgwk.WorkerReportsProgress = true; tagBgwk.DoWork -= BgwkBase_DoWork; tagBgwk.DoWork += BgwkBase_DoWork; tagBgwk.ProgressChanged -= BgwkBase_ProgressChanged; tagBgwk.ProgressChanged += BgwkBase_ProgressChanged; tagBgwk.RunWorkerCompleted -= BgwkBase_RunWorkerCompleted; tagBgwk.RunWorkerCompleted += BgwkBase_RunWorkerCompleted; tagBgwk.RunWorkerAsync(sBgwkDef.RunningAction); } protected void CancelBgwork(BackgroundWorker tagBgwk) { tagBgwk.CancelAsync(); } protected void BgwkBase_DoWork(object sender, DoWorkEventArgs e) { ((Action)e.Argument).Invoke(); } protected void BgwkBase_ProgressChanged(object sender, ProgressChangedEventArgs e) { if (fm11BgwkStatus != null) { fm11BgwkStatus.ProgMain.Value = e.ProgressPercentage > fm11BgwkStatus.ProgMain.Maximum ? fm11BgwkStatus.ProgMain.Maximum : e.ProgressPercentage; fm11BgwkStatus.ProgMain.PerformStep(); fm11BgwkStatus.LabMessage.Text = e.UserState.ToString(); fm11BgwkStatus.LabMessage.Refresh(); } SetMainStatus(e.UserState.ToString()); } protected void BgwkBase_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Cancelled) { } if (fm11BgwkStatus != null) { fm11BgwkStatus.Close(); fm11BgwkStatus = null; } } #endregion /// <summary> /// 當前BS繫結的Datatable提交變更 /// </summary> protected void BaseCurBSDTAccept() { if (CurBindingSource.DataSource is DataTable dtb) { dtb.AcceptChanges(); } else if (CurBindingSource.DataSource is DataSet dsb) { if (!string.IsNullOrEmpty(CurBindingSource.DataMember)) { dsb.Tables[CurBindingSource.DataMember].AcceptChanges(); } } } /// <summary> /// 當前BS繫結的Datatable回滾變更,並放棄當前新增