最近从WinForm转到了Web开发。根据界面要求。选择了比较火的Extjs,一接触到它,就和TreeList杠上了。这是一个老外写的插件。整体看来还不错。如果只是用来做数据展示的话。建议你用Extjs扩展的ColumnTree就足够了。但用来做数据编辑的话。在几列的情况下。它不能每一列都设置一个Editor,TreeGrid就要上场了。 百度了一把,还没有人写这方面的文章哦,对于这个二X树算法都避而不谈。
首先,TreeGrid的定义模式是和Grid是相同的。
代码
1 var DepRecord = Ext.data.Record.create
2 ([
3 { name: 'DdepSN' },
4 { name: 'DdepName' },
5 { name: 'DdepOffTel' },
6 { name: 'DdepExtTel' },
7 { name: 'DdepModTel' },
8 { name: 'DdepFax' },
9 { name: 'DdepMemo' },
10 { name: 'DdepShow', type: 'bool' },
11 { name: 'Pname' },
12 { name: '_id' },
13 { name: '_parent' },
14 { name: '_level' },
15 { name: '_lft' },
16 { name: '_rgt' },
17 { name: '_is_leaf', type: 'bool' },
18 { name: 'Timep' }
19 ]);
2 ([
3 { name: 'DdepSN' },
4 { name: 'DdepName' },
5 { name: 'DdepOffTel' },
6 { name: 'DdepExtTel' },
7 { name: 'DdepModTel' },
8 { name: 'DdepFax' },
9 { name: 'DdepMemo' },
10 { name: 'DdepShow', type: 'bool' },
11 { name: 'Pname' },
12 { name: '_id' },
13 { name: '_parent' },
14 { name: '_level' },
15 { name: '_lft' },
16 { name: '_rgt' },
17 { name: '_is_leaf', type: 'bool' },
18 { name: 'Timep' }
19 ]);
//TreeGrid专用的Store
20 HyOA.FrmHRDepList.DepStore = new Ext.ux.maximgb.treegrid.NestedSetStore
21 ({
22 autoLoad: true,
23 url: "./Project/System/FrmDepListService.aspx?Param=GetAllDepNode&&isHRDep=true",
24 reader: new Ext.data.JsonReader
25 ({ id: '_id', root: 'data', totalProperty: 'total', successProperty: 'success'
26 }, HyOA.FrmHRDepList.DepRecord)
27 });
28 var DepGrid = new Ext.ux.maximgb.treegrid.EditorGridPanel
29 ({
30 store: DepStore,
31 master_column_id: 'DdepSN',//重要属性。
32 region: 'center',
33 scope: this,
34 columns:
35 [
36 { id: 'DdepSN', header: "部门编号", dataIndex: "DdepSN", width: 150, sortable: true, editor: new Ext.grid.GridEditor(new Ext.form.TextField({ allowBlank: false })) },
37 { header: "部门名称", dataIndex: "DdepName", width: 260, sortable: true, editor: new Ext.grid.GridEditor(new Ext.form.TextField({ allowBlank: false })) },
38 { header: '办公电话', dataIndex: 'DdepOffTel', width: 130, editor: new Ext.grid.GridEditor(new Ext.form.TextField({ allowBlank: false })) },
39 { header: '电话分机', dataIndex: 'DdepExtTel', width: 130, editor: new Ext.grid.GridEditor(new Ext.form.TextField({ allowBlank: false })) },
40 { header: '移动座机', dataIndex: 'DdepModTel', width: 130, editor: new Ext.grid.GridEditor(new Ext.form.DateField({ allowBlank: false })) },
41 { header: '传真', dataIndex: 'DdepFax', width: 130, editor: new Ext.grid.GridEditor(new Ext.form.TextField({ allowBlank: false })) },
42 { header: "备注", width: 130, sortable: true, dataIndex: "DdepMemo", editor: new Ext.grid.GridEditor(new Ext.form.TextField()) },
43 { dataIndex: 'Timep', hidden: true }
44 ],
45 height: 220,
46 sm: new Ext.grid.RowSelectionModel({ singleSelect: true }),
47 stripeRows: true,
48 enableDD: true,
49 title: "部门分类",
50 viewConfig: { enableRowBody: true },
51 tbar: DepTBar
52 });
20 HyOA.FrmHRDepList.DepStore = new Ext.ux.maximgb.treegrid.NestedSetStore
21 ({
22 autoLoad: true,
23 url: "./Project/System/FrmDepListService.aspx?Param=GetAllDepNode&&isHRDep=true",
24 reader: new Ext.data.JsonReader
25 ({ id: '_id', root: 'data', totalProperty: 'total', successProperty: 'success'
26 }, HyOA.FrmHRDepList.DepRecord)
27 });
28 var DepGrid = new Ext.ux.maximgb.treegrid.EditorGridPanel
29 ({
30 store: DepStore,
31 master_column_id: 'DdepSN',//重要属性。
32 region: 'center',
33 scope: this,
34 columns:
35 [
36 { id: 'DdepSN', header: "部门编号", dataIndex: "DdepSN", width: 150, sortable: true, editor: new Ext.grid.GridEditor(new Ext.form.TextField({ allowBlank: false })) },
37 { header: "部门名称", dataIndex: "DdepName", width: 260, sortable: true, editor: new Ext.grid.GridEditor(new Ext.form.TextField({ allowBlank: false })) },
38 { header: '办公电话', dataIndex: 'DdepOffTel', width: 130, editor: new Ext.grid.GridEditor(new Ext.form.TextField({ allowBlank: false })) },
39 { header: '电话分机', dataIndex: 'DdepExtTel', width: 130, editor: new Ext.grid.GridEditor(new Ext.form.TextField({ allowBlank: false })) },
40 { header: '移动座机', dataIndex: 'DdepModTel', width: 130, editor: new Ext.grid.GridEditor(new Ext.form.DateField({ allowBlank: false })) },
41 { header: '传真', dataIndex: 'DdepFax', width: 130, editor: new Ext.grid.GridEditor(new Ext.form.TextField({ allowBlank: false })) },
42 { header: "备注", width: 130, sortable: true, dataIndex: "DdepMemo", editor: new Ext.grid.GridEditor(new Ext.form.TextField()) },
43 { dataIndex: 'Timep', hidden: true }
44 ],
45 height: 220,
46 sm: new Ext.grid.RowSelectionModel({ singleSelect: true }),
47 stripeRows: true,
48 enableDD: true,
49 title: "部门分类",
50 viewConfig: { enableRowBody: true },
51 tbar: DepTBar
52 });
这样就定义好了一个TreeGrid,除了它专用的NestedSetStore,其它的都与Grid的定义一致的。在Record里面有三个重要属性,level,_lft,_rgt,对应二X树里面的左右节点概念,最后附上生成代码
代码
static int nFit = 0;
Res = new DataTable();
nFit = 0;
DataColumn ColumnPid = new DataColumn("Pid", typeof(int));
DataColumn ColumnChild = new DataColumn("ChildID", typeof(int));
DataColumn ColumnLft = new DataColumn("Lft", typeof(int));
DataColumn ColumnRgt = new DataColumn("Rgt", typeof(int));
DataColumn ColumnLevel = new DataColumn("Level", typeof(int));
Res.Columns.AddRange(new DataColumn[] { ColumnPid, ColumnChild, ColumnLft, ColumnRgt, ColumnLevel });
Res.PrimaryKey = new DataColumn[] { ColumnChild };
AnalyzeLftRgt();
/// <summary>
/// 调用上面函数,完成计算,这里用了听棠的Orm
/// </summary>
private void AnalyzeLftRgt()
{
nFit = 0;
if (Res.Rows.Count > 0) Res.Rows.Clear();
RetrieveCriteria Tm = new RetrieveCriteria(typeof(tbDepListEntity));
Tm.DatabaseName = SessionManager.GetSession("LoginBase");
Tm.AddSelect(tbDepListEntity.__PID);
Tm.AddSelect(tbDepListEntity.__DEPID, "ChildID");
Tm.OrderBy(tbDepListEntity.__DEPSN);
Table = Tm.AsDataTable();
DataRow[] AllNode = Table.Select("PID=0");
for (int n = 0; n < AllNode.Length; n++)
{
DataRow Dr = AllNode[n];
int ID = Convert.ToInt32(Dr["ChildID"]);
DoWork(ID, 0);
}
}
/// <summary>
/// 生成Lft,Rgt,Level的专用函数。
/// </summary>
public void DoWork(int ID, int Pid)
{
int Level = 1;
DataRow PNode = Res.Rows.Find(Pid);
if (PNode != null)
{
Level = Convert.ToInt32(PNode["Level"]) + 1;
}
DataRow New = Res.NewRow();
New["Pid"] = Pid;
New["ChildID"] = ID;
New["Level"] = Level;
if (!Res.Rows.Contains(ID))
{
New["Lft"] = ++nFit;
Res.Rows.Add(New);
}
DataRow[] Rows = Table.Select("PID=" + ID.ToString());
if (Rows.Length > 0)
{
for (int i = 0; i < Rows.Length; i++)
{
DataRow Dr = Rows[i];
int ChildID = Convert.ToInt32(Dr["ChildID"]);
DoWork(ChildID, ID);
}
DataRow PRow = Res.Rows.Find(ID);
if (PRow != null)//遍历完兄弟后给老子赋Rgt的值
{
PRow["Rgt"] = ++nFit;
}
}
else
{
//没有儿子,给老子赋Rgt的值
New["Rgt"] = ++nFit;
}
}
Res = new DataTable();
nFit = 0;
DataColumn ColumnPid = new DataColumn("Pid", typeof(int));
DataColumn ColumnChild = new DataColumn("ChildID", typeof(int));
DataColumn ColumnLft = new DataColumn("Lft", typeof(int));
DataColumn ColumnRgt = new DataColumn("Rgt", typeof(int));
DataColumn ColumnLevel = new DataColumn("Level", typeof(int));
Res.Columns.AddRange(new DataColumn[] { ColumnPid, ColumnChild, ColumnLft, ColumnRgt, ColumnLevel });
Res.PrimaryKey = new DataColumn[] { ColumnChild };
AnalyzeLftRgt();
/// <summary>
/// 调用上面函数,完成计算,这里用了听棠的Orm
/// </summary>
private void AnalyzeLftRgt()
{
nFit = 0;
if (Res.Rows.Count > 0) Res.Rows.Clear();
RetrieveCriteria Tm = new RetrieveCriteria(typeof(tbDepListEntity));
Tm.DatabaseName = SessionManager.GetSession("LoginBase");
Tm.AddSelect(tbDepListEntity.__PID);
Tm.AddSelect(tbDepListEntity.__DEPID, "ChildID");
Tm.OrderBy(tbDepListEntity.__DEPSN);
Table = Tm.AsDataTable();
DataRow[] AllNode = Table.Select("PID=0");
for (int n = 0; n < AllNode.Length; n++)
{
DataRow Dr = AllNode[n];
int ID = Convert.ToInt32(Dr["ChildID"]);
DoWork(ID, 0);
}
}
/// <summary>
/// 生成Lft,Rgt,Level的专用函数。
/// </summary>
public void DoWork(int ID, int Pid)
{
int Level = 1;
DataRow PNode = Res.Rows.Find(Pid);
if (PNode != null)
{
Level = Convert.ToInt32(PNode["Level"]) + 1;
}
DataRow New = Res.NewRow();
New["Pid"] = Pid;
New["ChildID"] = ID;
New["Level"] = Level;
if (!Res.Rows.Contains(ID))
{
New["Lft"] = ++nFit;
Res.Rows.Add(New);
}
DataRow[] Rows = Table.Select("PID=" + ID.ToString());
if (Rows.Length > 0)
{
for (int i = 0; i < Rows.Length; i++)
{
DataRow Dr = Rows[i];
int ChildID = Convert.ToInt32(Dr["ChildID"]);
DoWork(ChildID, ID);
}
DataRow PRow = Res.Rows.Find(ID);
if (PRow != null)//遍历完兄弟后给老子赋Rgt的值
{
PRow["Rgt"] = ++nFit;
}
}
else
{
//没有儿子,给老子赋Rgt的值
New["Rgt"] = ++nFit;
}
}
最后希望用Extjs的菜鸟们能从这里得到一点帮助,不像我当时一样。是没有地方可以借鉴的。