行为定义引擎
设计原因: UI层 用户操作复杂 ,事件繁多,业务繁琐,控制代码粒度如果太大,重复代码太多,灵活性差,如果降低控制代码粒度, 重用性好,灵活性好,但是,方法太多,调用麻烦
设计目的:使用小粒度方法,达到调用方便灵活直观的目的
设计思路:使用通一输入输出方法签名 Action<Dictionary<string, object>, Action<object>, Action<object>> func = null; Dictionary<string, object> 是输入数据,第一个 Action<object> 是 成功后 执行方法,第二个 Action<object> 是失败后执行方法,
所有方法都使用这一签名
先构建XML状的方法树 ,引擎+模板
然后运行
这一行为定义引擎已在项目中使用 ,效果不错
行为定义引擎 代码如下
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Xml.Linq;
namespace LFRT5.clint.myControls
{
public class pageDo
{
public string name { get; set; }
public string xmlstring { get; set; }
//string neweve { get; set; }
//string newobj { get; set; }
// List<string[]> neweve = new List<string[]>();
XDocument doc = null;
public void eve(string objname, string evename, Func<string, string, Action<Dictionary<string, object>, Action<object>, Action<object>>> getfunc)
{
//try
//{
pageDoMode m = new pageDoMode();
doc = XDocument.Parse(xmlstring);
var e = geteveEle(objname, evename, doc);
m = createEve(getfunc, m, e);
if (m != null) m.dofun();
//if (neweve.Count > 0)
//{
// var newevetemp = neweve;
// neweve = new List<string[]>();
// foreach (var item in newevetemp)
// {
// var ev = item[0];
// var ob = item[1];
// eve(ob, ev, getfunc);
// }
//}
//}
//catch (Exception ee)
//{
// MessageBox.Show(ee.Message);
//}
}
private XElement geteveEle(string objname, string evename, XDocument doc)
{
var e = doc.Root.Element(name).Element(objname).Element(evename);
if (e == null)
{
e = doc.Root.Element("通用").Element(objname).Element(evename);
return null;
}
return e;
}
private pageDoMode createEve(Func<string, string, Action<Dictionary<string, object>, Action<object>, Action<object>>> getfunc, pageDoMode m, XElement xmlread)
{
var e = xmlread;
if (e.Attribute("type") != null && e.Attribute("type").Value == "neweve")
{
// string[] strs = new string[] { e.Name.LocalName, e.Attribute("objname").Value };
// neweve.Add(strs);
// return null;
e = geteveEle(e.Attribute("objname").Value, e.Name.LocalName, doc);
}
{
Action<Dictionary<string, object>, Action<object>, Action<object>> fun = null;
if (e.Attribute("type") != null && e.Attribute("type").Value == "eve")
{
fun = (invalue, ok, err) => { ok(System.DBNull.Value); };
}
else
fun = getfunc(e.Attribute("objname").Value, e.Name.LocalName);
if (fun == null) throw new Exception("fun is null " + e.Name.LocalName);
m.func = fun;
var ns = e.Nodes();
foreach (var item in ns)
{
var el = item as XElement;
if (el == null) continue;
var n = el.Name.LocalName;
switch (n)
{
case "inv":
var tns2 = el.Nodes();
foreach (var item1 in tns2)
{
var el1 = item1 as XText;
if (el1 == null || string.IsNullOrEmpty(el1.Value)) continue;
m.invalue.Add(el.Attribute("vname").Value, el1.Value);
}
break;
case "in":
var tns3 = el.Nodes();
foreach (var item1 in tns3)
{
var el1 = item1 as XElement;
if (el1 == null) continue;
var f = getfunc(el1.Attribute("objname").Value, el1.Name.LocalName);
if (f == null) continue;
m.GetValue.Add(el.Attribute("vname").Value, f);
}
break;
case "ok":
var tns = el.Nodes();
foreach (var item1 in tns)
{
var el1 = item1 as XElement;
if (el1 == null) continue;
var okm = createEve(getfunc, new pageDoMode(), el1);
if (okm != null) m.ok.Add(okm);
}
break;
case "err":
var tns1 = el.Nodes();
foreach (var item1 in tns1)
{
var el1 = item1 as XElement;
if (el1 == null) continue;
var errm = createEve(getfunc, new pageDoMode(), el1);
if (errm != null) m.err.Add(errm);
}
break;
}
}
// fun(ok, err);
}
return m;
}
}
public class pageDoMode
{
public Dictionary<string, Action<Dictionary<string, object>, Action<object>, Action<object>>> GetValue = new Dictionary<string, Action<Dictionary<string, object>, Action<object>, Action<object>>>(); //new List<Action<List<object>, Action<object>, Action<object>>>();
// public List<object> invalue = new List<object>();
public Dictionary<string, object> invalue = new Dictionary<string, object>();
public List<pageDoMode> ok = new List<pageDoMode>();
public List<pageDoMode> err = new List<pageDoMode>();
public Action<Dictionary<string, object>, Action<object>, Action<object>> func = null;
public void dofun()
{
if (GetValue != null)
{
foreach (var item in GetValue)
{
object obj = null;
item.Value(null, (o) => { obj = o; }, null);
if (!(obj is DBNull)) invalue.Add(item.Key, obj);
}
}
func(invalue,
(o) =>
{
if (ok == null || ok.Count == 0) return;
ok.ForEach((c) =>
{
if (!(o is DBNull)) { if(c.invalue.ContainsKey("ok"))c.invalue.Remove("ok"); c.invalue.Add("ok", o); }
c.dofun();
});
},
(o) =>
{
if (err == null || err.Count == 0) return;
err.ForEach((c) => { c.invalue.Add("error", o); c.dofun(); });
});
}
}
}
行为定义模板XML
<?xml version="1.0" encoding="utf-8" ?>
<pagedo>
<员工管理>
<页面>
<页面初始化 type="eve">
<ok>
<datagrid添加资源 objname="页面">
<inv vname="dts">sel,v04,view03,_v06,v06</inv>
</datagrid添加资源>
<Fun_str_int2_m15 objname="通用数据服务">
<inv vname="command">获得人员列</inv>
<ok>
<datagrid列绑定 objname="页面"/>
</ok>
<err>
<消息 objname="页面"/>
</err>
</Fun_str_int2_m15>
<Fun_str_int2_m5 objname="通用数据服务">
<inv vname="command">获得功能信息</inv>
<ok>
<功能绑定 objname="页面"/>
</ok>
<err>
<消息 objname="页面"/>
</err>
</Fun_str_int2_m5>
<查询数据 type="neweve" objname="页面" />
<部门数据绑定 type="neweve" objname="页面" />
<Fun_str_int2_m5 objname="通用数据服务">
<inv vname="command">获得仅部门信息</inv>
<ok>
<datagrid_comdata数据绑定 objname="页面"/>
</ok>
<err>
<消息 objname="页面"/>
</err>
</Fun_str_int2_m5>
</ok>
</页面初始化>
<部门数据绑定 type="eve">
<ok>
<Fun_str_ns_m5 objname="通用数据服务">
<inv vname="command">获得部门信息</inv>
<ok>
<mytreeview数据绑定 objname="页面"/>
</ok>
<err>
<消息 objname="页面"/>
</err>
</Fun_str_ns_m5>
</ok>
</部门数据绑定>
<部门改变 type="eve">
<ok>
<查询数据 type="neweve" objname="页面" />
</ok>
</部门改变 >
<查询数据 type="eve">
<ok>
<Fun_str_int objname="通用数据服务">
<inv vname="command">获得人员数量信息</inv>
<in vname="filters">
<获得查询字符串 objname="页面"/>
</in>
<ok>
<datagrid数量绑定 objname="页面"/>
</ok>
<err>
<消息 objname="页面"/>
</err>
</Fun_str_int>
</ok>
</查询数据>
<datagrid翻页 type="eve">
<ok>
<人员查询 type="neweve" objname="页面" />
</ok>
</datagrid翻页>
<人员查询 type="eve">
<ok>
<Fun_str_int2_m20 objname="通用数据服务">
<inv vname="command">获得人员数据信息</inv>
<in vname="filters">
<获得查询字符串 objname="页面"/>
</in>
<in vname="start">
<datagrid起始行号 objname="页面"/>
</in>
<in vname="end">
<datagrid截至行号 objname="页面"/>
</in>
<ok>
<datagrid数据绑定 objname="页面"/>
</ok>
<err>
<消息 objname="页面"/>
</err>
</Fun_str_int2_m20>
</ok>
</人员查询>
<关闭部门编辑窗口 type="eve">
<ok>
<关闭部门编辑窗口 objname="页面"/>
</ok>
</关闭部门编辑窗口>
<部门编辑确认 type="eve">
<ok>
<Fun_m5_int objname="通用数据服务">
<inv vname="command">部门数据保存</inv>
<in vname="m">
<获得部门编辑数据 objname="页面"/>
</in>
<ok>
<部门数据绑定 type="neweve" objname="页面" />
<关闭部门编辑窗口 type="neweve" objname="页面" />
</ok>
<err>
<消息 objname="页面"/>
</err>
</Fun_m5_int>
</ok>
</部门编辑确认>
</页面>
<员工控制>
<按钮只读 type="eve">
<ok>
<按钮控制 objname="员工控制">
<inv vname="name">*</inv>
<inv vname="enble">true</inv>
</按钮控制>
<按钮控制 objname="员工控制">
<inv vname="name">撤销,保存</inv>
<inv vname="enble">false</inv>
</按钮控制>
</ok>
</按钮只读>
<按钮编辑 type="eve">
<ok>
<按钮控制 objname="员工控制">
<inv vname="name">*</inv>
<inv vname="enble">true</inv>
</按钮控制>
<按钮控制 objname="员工控制">
<inv vname="name">新建,删除,修改</inv>
<inv vname="enble">false</inv>
</按钮控制>
</ok>
</按钮编辑>
<初始化完成 type="eve">
<ok>
<按钮只读 type="neweve" objname="员工控制" />
</ok>
</初始化完成>
<新建 type="eve">
<ok>
<按钮编辑 type="neweve" objname="员工控制" />
<Fun_str_m20 objname="通用数据服务">
<inv vname="command">新建人员数据</inv>
<in vname="m">
<获得人员编辑数据 objname="页面"/>
</in>
<ok>
<datagrid添加行 objname="页面"/>
</ok>
<err>
<消息 objname="页面"/>
</err>
</Fun_str_m20>
<datagrid只读 objname="页面">
<inv vname="IsReadOnly">false</inv>
</datagrid只读>
</ok>
</新建>
<修改 type="eve">
<ok>
<按钮编辑 type="neweve" objname="员工控制" />
<datagrid只读 objname="页面">
<inv vname="IsReadOnly">false</inv>
</datagrid只读>
</ok>
</修改>
<删除 type="eve">
<ok>
<datagrid删除询问>
<ok>
<Fun_m20s_int objname="通用数据服务">
<inv vname="command">人员数据删除</inv>
<in vname="m">
<获得datagrid勾选行 objname="页面"/>
</in>
<ok>
<人员查询 type="neweve" objname="页面"/>
</ok>
<err>
<消息 objname="页面"/>
</err>
</Fun_m20s_int>
</ok>
</datagrid删除询问>
</ok>
</删除>
<撤销 type="eve">
<ok>
<按钮只读 type="neweve" objname="员工控制" />
<人员查询 type="neweve" objname="页面"/>
<datagrid只读 objname="页面">
<inv vname="IsReadOnly">true</inv>
</datagrid只读>
</ok>
</撤销>
<保存 type="eve">
<ok>
<Fun_m20s_int objname="通用数据服务">
<inv vname="command">人员数据保存</inv>
<in vname="m">
<获得datagrid编辑行 objname="页面"/>
</in>
<ok>
<按钮只读 type="neweve" objname="员工控制" />
<人员查询 type="neweve" objname="页面"/>
<datagrid只读 objname="页面">
<inv vname="IsReadOnly">true</inv>
</datagrid只读>
</ok>
<err>
<消息 objname="页面"/>
</err>
</Fun_m20s_int>
</ok>
</保存>
<EXCEL type="eve">
<ok>
<Fun_str_int2_m20 objname="通用数据服务">
<inv vname="command">获得人员数据信息</inv>
<in vname="filters">
<获得查询字符串 objname="页面"/>
</in>
<ok>
<导出到EXCEL objname="页面">
<in vname="columns">
<获得datagrid列 objname="页面"></获得datagrid列>
</in>
</导出到EXCEL>
</ok>
<err>
<消息 objname="页面"/>
</err>
</Fun_str_int2_m20>
</ok>
</EXCEL>
</员工控制>
<部门控制>
<初始化完成 type="eve">
</初始化完成>
<新建部门 type="eve">
<ok>
<Fun_str_int2_m15 objname="通用数据服务">
<inv vname="command">获得部门列</inv>
<ok>
<部门新建 objname="页面"/>
</ok>
<err>
<消息 objname="页面"/>
</err>
</Fun_str_int2_m15>
</ok>
</新建部门>
<删除部门 type="eve">
<ok>
<部门删除询问 objname="页面">
<ok>
<Fun_m5_int objname="通用数据服务">
<inv vname="command">部门数据删除</inv>
<in vname="m">
<获得部门选择数据 objname="页面"/>
</in>
<ok>
<部门数据绑定 type="neweve" objname="页面" />
</ok>
<err>
<消息 objname="页面"/>
</err>
</Fun_m5_int>
</ok>
</部门删除询问>
</ok>
</删除部门>
<机构修改 type="eve">
<ok>
<Fun_str_int2_m15 objname="通用数据服务">
<inv vname="command">获得部门列</inv>
<ok>
<部门修改 objname="页面"/>
</ok>
<err>
<消息 objname="页面"/>
</err>
</Fun_str_int2_m15>
</ok>
</机构修改>
</部门控制>
</员工管理>
</pagedo>
使用代码示例如下
public pageDo pagedoobj
{
get
;
set
;
}
pagedoobj.xmlstring = xml;
pagedoobj.name = name;
pagedoobj.eve("页面", "页面初始化", getFun);
public Action<Dictionary<string, object>, Action<object>, Action<object>> getFun(string objname, string evename)
{
Action<Dictionary<string, object>, Action<object>, Action<object>> func = null;
switch (objname)
{
case "页面":
default :
switch (evename)
{
case "datagrid添加资源":
func = (invs, ok, err) =>
{
var dtstr = invs["dts"] as string;
var dtstrs = dtstr.Split(',');
foreach (var item in dtstrs)
{
if (mainpage.Resources.Contains(item))
mainpage.mydatagrid1.myDataTemplate.Add(item, mainpage.Resources[item]);
}
};
break;
case "mytreeview数据绑定":
func = (invs, ok, err) =>
{
var bmdata = invs["ok"];
if (bmdata == null) return;
var obj = mainpage.myTreeView_bm.treeView1.DataContext;
mainpage.myTreeView_bm.treeView1.DataContext = bmdata;
if (obj != null) mainpage.myTreeView_bm.treeView1.OnApplyTemplate();
// mainpage.myTreeView_bm.treeView1.DataContext = bmdata;
if (ok != null) ok(DBNull.Value);
};
break;
case "功能绑定":
func = (invs, ok, err) =>
{
var data = invs["ok"];
if (data == null) return;
LFRT5.clint.util.initMyTabButtons(mainpage.tabButtons1, data as List<Model5>);
LFRT5.clint.util.initMyTabButtons(mainpage.tabButtons3, data as List<Model5>);
if (ok != null) ok(DBNull.Value);
};
break;
case "datagrid只读":
func = (invs, ok, err) =>
{
var data = Convert.ToBoolean(invs["IsReadOnly"]);
mainpage.mydatagrid1.dataGrid1.IsReadOnly = data;
if (ok != null) ok(DBNull.Value);
};
break;
case "datagrid列绑定":
func = (invs, ok, err) =>
{
var data = invs["ok"];
if (data == null) return;
mainpage.mydatagrid1.GridAddColumn(data as List<Model15>);
if (ok != null) ok(DBNull.Value);
};
break;
case "获得datagrid列":
func = (invs, ok, err) =>
{
if (ok != null) ok(mainpage.mydatagrid1.gridColumns);
};
break;
case "datagrid数量绑定":
func = (invs, ok, err) =>
{
var data = invs["ok"];
if (data == null) return;
mainpage.mydatagrid1.customDataPager1.DataCount = (int)data;
if (ok != null) ok(DBNull.Value);
};
break;
case "datagrid数据绑定":
func = (invs, ok, err) =>
{
var data = invs["ok"];
if (data == null) return;
mainpage.mydatagrid1.dataGrid1.DataContext = data;
var ms = mainpage.mydatagrid1.dataGrid1.DataContext as System.Collections.IList;
foreach (var item in ms)
{
dynamic m = item;
m.vc01 = "false";
}
if (ok != null) ok(DBNull.Value);
};
break;
case "datagrid_comdata数据绑定":
func = (invs, ok, err) =>
{
var data = invs["ok"];
if (data == null) return;
var collectionView = mainpage.Resources["comdata"] as System.Windows.Data.CollectionViewSource;
collectionView.Source = data;
if (ok != null) ok(DBNull.Value);
};
break;
case "获得datagrid勾选行":
func = (invs, ok, err) =>
{
var ms = mainpage.mydatagrid1.dataGrid1.DataContext as System.Collections.IList;
var ds = new List<object>();
foreach (var item in ms)
{
dynamic d = item;
if (Convert.ToBoolean(d.vc01))
{
ds.Add(item);
}
}
if (ok != null) ok(ds);
};
break;
case "获得datagrid编辑行":
func = (invs, ok, err) =>
{
var ms = mainpage.mydatagrid1.dataGrid1.DataContext as System.Collections.IList;
var ds = new List<object>();
foreach (var item in ms)
{
dynamic d = item;
if (Convert.ToInt32(d.id)<0)
{
ds.Add(item);
}
}
if (ok != null) ok(ds);
};
break;
case "datagrid添加行":
func = (invs, ok, err) =>
{
var data = invs["ok"];
if (data == null) return;
var ms = mainpage.mydatagrid1.dataGrid1.DataContext as System.Collections.IList;
ms.Insert(0, data);
mainpage.mydatagrid1.dataGrid1.OnApplyTemplate();
if (ok != null) ok(DBNull.Value);
};
break;
case "datagrid起始行号":
func = (invs, ok, err) =>
{
if (ok != null) ok(mainpage.mydatagrid1.customDataPager1.rowStart);
};
break;
case "datagrid截至行号":
func = (invs, ok, err) =>
{
if (ok != null) ok(mainpage.mydatagrid1.customDataPager1.rowEnd);
};
break;
case "datagrid删除询问":
func = (invs, ok, err) =>
{
if (util.MessageBoxShow(mainwin, "确定删除数据么?", "删除", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
{
if (ok != null) ok(DBNull.Value);
}
};
break;
case "获得查询字符串":
func = (invs, ok, err) =>
{
string str = "";
var n = mainpage.myTreeView_bm.treeView1.SelectedItem as Node;
if (n != null && !string.IsNullOrEmpty(n.Text))
{
str += "view01=" + n.Text + "|view03=" + n.Text;
}
var m = mainpage.dataForm11.CurrentItem as LFRT5.db.models.Model5;
if (m != null && !string.IsNullOrEmpty(m.v01))
{
if (!string.IsNullOrEmpty(str)) str += "|";
str += "v01^" + m.v01 + "|v02^" + m.v01 + "|v03^" + m.v01 + "|v04^" + m.v01 + "|v05^" + m.v01;
}
if (ok != null) ok(str);
};
break;
case "部门修改":
func = (invs, ok, err) =>
{
var columns = invs["ok"];
ShowWindow_bumen("修改", evename, columns);
if (ok != null) ok(wbumen);
};
break;
case "部门新建":
func = (invs, ok, err) =>
{
var columns = invs["ok"];
ShowWindow_bumen("新建", evename, columns);
if (ok != null) ok(wbumen);
};
break;
case "关闭部门编辑窗口":
func = (invs, ok, err) =>
{
mainGrid.Children.Remove(wbumen);
wbumen = null;
if (ok != null) ok(DBNull.Value);
};
break;
case "部门删除询问":
func = (invs, ok, err) =>
{
var b = bumenDeleteDataTel();
if (!b) return;
if (ok != null) ok(DBNull.Value);
};
break;
case "获得部门GUID":
func = (invs, ok, err) =>
{
var guid = ((ObservableCollection<Node>)(mainpage.myTreeView_bm.treeView1.DataContext))[0].model.guid;
if (ok != null) ok(guid);
};
break;
case "获得部门编辑数据":
func = (invs, ok, err) =>
{
var d = (wbumen.dataForm11.DataContext as List<Model15>)[0];
if (string.IsNullOrEmpty(d.v02)) d.v02 = ((ObservableCollection<Node>)(mainpage.myTreeView_bm.treeView1.DataContext))[0].model.guid;
Model5 m = new Model5();
util.Tconvert<Model5, Model15>(ref m, d);
if (ok != null) ok(m);
};
break;
case "获得部门选择数据":
func = (invs, ok, err) =>
{
var d = ((Node)(mainpage.myTreeView_bm.treeView1.SelectedItem)).model;
Model5 m = new Model5();
util.Tconvert<Model5, Model15>(ref m, d);
if (ok != null) ok(m);
};
break;
case "消息":
func = (invalue, ok, err) => { util.MessageBoxShow(mainwin, invalue["error"] as string); };
break;
case "导出到EXCEL":
func = (invalue, ok, err) => {
var columns = invalue["columns"] as List<Model15> ;
var ds = invalue["ok"] as System.Collections.IList;
var newds = new List<object>();
foreach (var item in ds)
{
newds.Add(item);
}
util.toExcel(columns, newds);
};
break;
}
break;
case "员工控制":
func = mainpage.tabButtons1.getFunc(evename);
break;
case "部门控制":
func = mainpage.tabButtons3.getFunc(evename);
break;
case "通用数据服务":
func = svc.getFunc(evename);
break;
return null;
}
return func;
}