功能清單
- 輸入前鎖定非關鍵控制項
- 必填欄位空值驗證
- 輸入格式正則驗證
- 一鍵清空畫面
- 設定控制項預設值
- 清除錯誤提示訊息
- 資料列 → 編輯控制項 映射
- 編輯控制項 → 資料列 回寫
核心實體:SetControl
public class SetControl
{
[Description("控制項名稱")] public object ControlName { get; set; }
[Description("可否為空")] public bool NullAble { get; set; }
[Description("預設值")] public object Default { get; set; }
[Description("匹配格式(Regex)")] public string Format { get; set; }
[Description("是否主鍵")] public bool KeyFiled { get; set; }
[Description("對應欄位名稱")] public string FiledName { get; set; }
public override string ToString() {
var prop = ControlName.GetType().GetProperty("Name");
return prop?.GetValue(ControlName, null)?.ToString() ?? "";
}
}
抽象操作介面:TypeProcess
public abstract class TypeProcess
{
protected SetControl _setCtrl;
protected TypeProcess(SetControl sender) { _setCtrl = sender; }
public abstract bool CheckNull();
public abstract bool CheckFormat();
public abstract void SetCtrlClear();
public abstract void SetCtrlEnable(bool enable);
public abstract void SetCtrlDefault();
public abstract void ClearErrText();
public abstract void LoadToText(DataRow row);
public abstract void SetTextToRow(DataRow row);
}
具體實作範例
TextEditProcess (DevExpress TextEdit)
public class TextEditProcess : TypeProcess
{
DevExpress.XtraEditors.TextEdit txt;
public TextEditProcess(SetControl sender) : base(sender) { txt = _setCtrl.ControlName as DevExpress.XtraEditors.TextEdit; }
public override bool CheckNull() {
if (!_setCtrl.NullAble && string.IsNullOrWhiteSpace(txt.Text)) {
txt.ErrorText = "不能為空"; txt.Focus(); return false;
} return true;
}
public override bool CheckFormat() {
if (!string.IsNullOrEmpty(_setCtrl.Format) && !Regex.IsMatch(txt.Text, $"^{_setCtrl.Format}$")) {
txt.ErrorText = "輸入格式不正確"; txt.Focus(); return false;
} return true;
}
public override void SetCtrlClear() => txt.EditValue = null;
public override void SetCtrlEnable(bool enable) => txt.Enabled = _setCtrl.KeyFiled ? enable : !enable;
public override void SetCtrlDefault() => txt.EditValue = _setCtrl.Default;
public override void ClearErrText() => txt.ErrorText = string.Empty;
public override void LoadToText(DataRow row) { if (!string.IsNullOrEmpty(_setCtrl.FiledName)) txt.EditValue = row[_setCtrl.FiledName]; }
public override void SetTextToRow(DataRow row) { if (!string.IsNullOrEmpty(_setCtrl.FiledName)) row[_setCtrl.FiledName] = txt.EditValue; }
}
ComboBoxEditProcess
public class ComboBoxEditProcess : TypeProcess
{
DevExpress.XtraEditors.ComboBoxEdit comb;
public ComboBoxEditProcess(SetControl sender) : base(sender) { comb = _setCtrl.ControlName as DevExpress.XtraEditors.ComboBoxEdit; }
public override bool CheckNull() { /* 檢查 EditValue 是否為 null */ }
public override bool CheckFormat() => true; // 下拉選單通常不需格式驗證
// 其他方法類似 TextEditProcess,操作 comb.EditValue
}
反射工廠與快取
public class TypeFactory
{
public static TypeProcess CreateType(string type, object[] obj, string ctrlCnm, TypeCache cache)
{
if (cache.ExistObject(ctrlCnm)) return cache.GetObject(ctrlCnm) as TypeProcess;
var process = (TypeProcess)Assembly.Load("RealSailing.BizControls")
.CreateInstance($"RealSailing.UI.Utils.{type}Process", false, BindingFlags.Default, null, obj, new CultureInfo("zh-CN"), null);
cache.AddObject(ctrlCnm, process);
return process;
}
}
public class TypeCache
{
readonly Hashtable htObj = Hashtable.Synchronized(new Hashtable());
public void AddObject(string name, object instance) { if (!htObj.ContainsKey(name)) htObj.Add(name, instance); }
public void DeleteObject(string name) { if (htObj.ContainsKey(name)) htObj.Remove(name); }
public object GetObject(string name) => htObj.ContainsKey(name) ? htObj[name] : null;
public bool ExistObject(string name) => htObj.ContainsKey(name);
public void ClearObject() => htObj.Clear();
}
統一入口:ControlValidation
public class ControlValidation
{
readonly TypeCache typeCache = new TypeCache();
List ctrlCollect = new List();
public List CtrlCollect { get => ctrlCollect; set => ctrlCollect = value; }
// 8 大公開方法皆採相同模式:遍歷 ctrlCollect → TypeFactory.CreateType → 呼叫對應 TypeProcess 方法
// 範例:
public bool CheckIsNull() {
foreach (var ctrl in ctrlCollect) {
var proc = TypeFactory.CreateType(ctrl.ControlName.GetType().Name, new object[]{ctrl}, ctrl.ToString(), typeCache);
if (!proc.CheckNull()) return false;
} return true;
}
// ... CheckIsFormat, SetCtrlClear, SetCtrlEnable, SetCtrlDefault, ClearErrText, LoadEditRowToText, SetCtrlTextToEditRow
}
使用範例
ControlValidation validate = new ControlValidation();
void Init() {
validate.CtrlCollect = new List {
new SetControl { ControlName=CombRegionType, FiledName="MSTM030_REGIONTYPE", Default=null, KeyFiled=true, NullAble=false, Format="" },
new SetControl { ControlName=txtRegionCd, FiledName="MSTM030_REGIONCD", Default=null, KeyFiled=true, NullAble=false, Format="" },
new SetControl { ControlName=CombCompanyId, FiledName="MSTM030_COMID", Default=null, KeyFiled=false, NullAble=true, Format="" }
};
}
// 於 Form Load 或建構函數呼叫 Init()
// 之後即可隨時呼叫 validate.SetCtrlClear()、validate.CheckIsNull() 等
架構優勢
- 開放封閉原則:新增控制項型別只需增加對應
XXXProcess 類別
- 反射工廠解耦:主邏輯不依賴具體控制項型別
- 實例快取:避免重複建立
TypeProcess 物件
- 統一介面:8 大功能一致性呼叫