支持树型的GridView
实现思路 继承自Gridview处理gridview的数据源使其在帮定时就已经按照树型菜单顺序排列好那样只需在帮定处理其图片是javascript脚本就可以了
源代码下载
效果图
using System;
using SystemData;
using SystemCollections;
using SystemCollectionsSpecialized;
using SystemCollectionsGeneric;
using SystemComponentModel;
using SystemText;
using SystemWeb;
using SystemIO;
using SystemDrawing;
using SystemDrawingDesign;
using SystemReflection;
using SystemWebUI;
using SystemWebUIWebControls;
using SystemWebUIHtmlControls;
[ToolboxData(<{}:TreeListView runat=server></{}:TreeListView>) DefaultProperty(Text)]
public class TreeListView : GridView IPostBackDataHandler
{
public TreeListView()
{
baseAllowPaging = false;
baseAllowSorting = false;
baseAutoGenerateColumns = false;
}
Tree的属性设置#region Tree的属性设置
private int _nodeColumnIndex;
/**//// <summary>
/// 显示树型的列 Index
/// </summary>
public int NodeColumnIndex
{
get { return this_nodeColumnIndex; }
set
{
_nodeColumnIndex = value;
}
}
private string _columnKey;
/**//// <summary>
/// Key字段
/// </summary>
public string ColumnKey
{
get { return _columnKey; }
set
{
_columnKey = value;
}
}
private string _parentKey;
/**//// <summary>
/// 指向父节点的字段
/// </summary>
public string ParentKey
{
set
{
_parentKey = value;
}
}
private string _sortKey;
/**//// <summary>
/// 排序字段
/// </summary>
public string SortKey
{
set { _sortKey = value; }
}
private object _rootNodeFlag;
/**//// <summary>
/// 根节点的标记 这里采用 ParentKey为什么字符
/// </summary>
public object RootNodeFlag
{
set
{
_rootNodeFlag = value;
}
}
private static string _treeImageFolder = /Images/Tree/;
public static string TreeImageFolder
{
get
{
return _treeImageFolder;
}
set
{
_treeImageFolder = value;
}
}
private int _expendDepth = ;
/**//// <summary>
/// 展开的深度
/// </summary>
public int ExpendDepth
{
get
{
return _expendDepth;
}
set { _expendDepth = value; }
}
#endregion
public override object DataSource
{
get
{
return baseDataSource;
}
set
{
DataTable dtSource = new DataTable();
if (value is DataSet && ((DataSet)value)TablesCount > )
{
DataSet ds = value as DataSet;
dtSource = OrderData(dsTables[]);
}
else
{
throw new Exception(DataSource is not DataSet!);
}
baseDataSource = dtSource;
}
}
DataTable OrderData(DataTable dtSource)
{
DataTable dtResult = dtSourceClone();
dtResultColumnsAdd(TreeListView$Row$Depth typeof(int));
dtResultColumnsAdd(TreeListView$Row$IsLeaf typeof(bool));
dtResultColumnsAdd(TreeListView$Row$IsBottom typeof(bool));
dtResultColumnsAdd(TreeListView$Row$ParentRow typeof(DataRow));
dtResultColumnsAdd(TreeList$ViewRow$ClientID typeof(string));
RecursionOrderData(dtSource dtResult _rootNodeFlag null);
return dtResult;
}
string FormatToRowFilter(object val)
{
Type type = valGetType();
if (type == typeof(string))
{
return stringFormat({} valToString()Replace( ));
}
else if (type == typeof(Guid))
{
return stringFormat({} val);
}
else if (typeIsValueType)
{
return valToString();
}
else
{
return stringFormat({} valToString()Replace( ));
}
}
bool RecursionOrderData(DataTable dtSource DataTable dtResult object parentID int depth DataRow parentDatarow)
{
DataView dv = new DataView(dtSource);
dvRowFilter = stringFormat({}={} _parentKey FormatToRowFilter(parentID));
dvSort = _sortKey;
DataRow dr = null;
depth++;
for (int i = ; i < dvCount; i++)
{
dr = dtResultNewRow();
for (int j = ; j < dv[i]RowItemArrayLength; j++)
{
dr[j] = dv[i][j];
}
if (i == dvCount ) //isBottom
{
dr[TreeListView$Row$IsBottom] = true;
}
else
{
dr[TreeListView$Row$IsBottom] = false;
}
dr[TreeListView$Row$Depth] = depth;
dr[TreeListView$Row$ParentRow] = parentDatarow;
if (depth == )
{
dr[TreeList$ViewRow$ClientID] = GuidNewGuid()ToString();
}
else
{
dr[TreeList$ViewRow$ClientID] = parentDatarow[TreeList$ViewRow$ClientID]ToString() + / + GuidNewGuid()ToString();
}
dtResultRowsAdd(dr);
dr[TreeListView$Row$IsLeaf] = !RecursionOrderData(dtSource dtResult dv[i][_columnKey] depth dr);
}
return dvCount > ;
}
public override bool AllowPaging
{
get
{
return baseAllowPaging;
}
set
{
baseAllowPaging = false;
}
}
public override bool AutoGenerateColumns
{
get
{
return baseAutoGenerateColumns;
}
set
{
baseAutoGenerateColumns = false;
}
}
重载:CreateRow#region 重载:CreateRow
protected override GridViewRow CreateRow(int rowIndex int dataSourceIndex DataControlRowType rowType DataControlRowState rowState)
{
return new TreeListViewRow(rowIndex dataSourceIndex rowType rowState);
}
#endregion
重写:Rows#region 重写:Rows
private TreeListViewRowCollection _rowsCollection;
[Browsable(false)]
public new TreeListViewRowCollection Rows
{
get
{
ArrayList _rowsArray = new ArrayList();
for (int i = ; i < baseRowsCount; i++)
{
_rowsArrayAdd((TreeListViewRow)baseRows[i]);
}
this_rowsCollection = new TreeListViewRowCollection(_rowsArray);
return this_rowsCollection;
}
}
#endregion
重载:OnInit#region 重载:OnInit
protected override void OnInit(EventArgs e)
{
baseOnInit(e);
PageRegisterRequiresPostBack(this);
if (!PageClientScriptIsClientScriptIncludeRegistered(JS_TreeListView))
{
thisPageClientScriptRegisterClientScriptInclude(thisGetType() JS_TreeListView PageClientScriptGetWebResourceUrl(thisGetType() GoldMantisWebUIResourceTreeListViewJS_TreeListViewjs));
}
}
#endregion
IPostBackDataHandler Members#region IPostBackDataHandler Members
public bool LoadPostData(string postDataKey NameValueCollection postCollection)
{
return false;
}
public void RaisePostDataChangedEvent()
{
}
#endregion
方法:RenderCheckBoxExField#region 方法:RenderCheckBoxExField
/**//// <summary>
/// 处理CheckBoxExField类型的列
/// </summary>
private void RenderCheckBoxExField()
{
if (!thisShowHeader && !thisShowFooter)
{
return;
}
foreach (DataControlField field in Columns)
{
if (field is CheckBoxExField)
{
int checkBoxExFieldIndex = ColumnsIndexOf(field) + thisGetAutoGenerateButtonCount();
foreach (GridViewRow row in Rows)
{
if (rowRowType == DataControlRowTypeHeader)
{
rowCells[checkBoxExFieldIndex]ControlsClear();
}
if (rowRowType == DataControlRowTypeDataRow)
{
rowCells[checkBoxExFieldIndex]Controls[]ID = cbChoose;
((CheckBox)rowCells[checkBoxExFieldIndex]Controls[])AttributesAdd(onclick ChooseTree(this););
}
}
注册脚本#region 注册脚本
string script = @
var modifyId = ;
var choosedId = ;
var choosedIndex;
function ChooseTree(obj)
{
var cTrId = objparentElementparentElementparentElementid;
var treeTable = documentgetElementById(+thisClientID+@);
for( var i = ; i < treeTablerowslength; i++ )
{
if( treeTablerows[i]idindexOf(cTrId) != && treeTablerows[i]id != cTrId )
{
documentgetElementById(treeTablerows[i]id+_cbChoose)checked = objchecked;
}
}
choosedId = ;
choosedIndex = new Array();
for( var i = ; i < treeTablerowslength; i++ )
{
if( documentgetElementById(treeTablerows[i]id+_cbChoose)checked )
{
choosedId += treeTablerows[i]idsubstring(treeTablerows[i]idlastIndexOf(/)+) + ;
choosedIndexpush(i);
}
}
choosedId = choosedIdsubstring(choosedIdlength);
};
if (!PageClientScriptIsStartupScriptRegistered(TreeListView_CheckBoxExField))
{
PageClientScriptRegisterStartupScript(GetType() TreeListView_CheckBoxExField script true);
}
#endregion
}
}
}
方法:GetAutoGenerateButtonCount#region 方法:GetAutoGenerateButtonCount
private int GetAutoGenerateButtonCount()
{
int num = ;
if (thisAutoGenerateDeleteButton || thisAutoGenerateEditButton || thisAutoGenerateSelectButton)
{
num = ;
}
return num;
}
#endregion
#endregion
protected override void Render(HtmlTextWriter writer)
{
RenderCheckBoxExField();
baseRender(writer);
}
}
public class TreeListViewRow : GridViewRow
{
public TreeListViewRow(int rowIndex int dataItemIndex DataControlRowType rowType DataControlRowState rowState)
: base(rowIndex dataItemIndex rowType rowState)
{
}
protected override void OnPreRender(EventArgs e)
{
baseOnPreRender(e);
if (thisRowType == DataControlRowTypeDataRow)
{
if (thisParentParent is TreeListView)
{
TreeListView treeListView = thisParentParent as TreeListView;
DataRow dr = ((DataTable)treeListViewDataSource)Rows[thisDataItemIndex] as DataRow;
string str = GetTreeNodeImg(dr ConvertToBoolean(dr[TreeListView$Row$IsLeaf]) ConvertToBoolean(dr[TreeListView$Row$IsBottom]));
thisCells[treeListViewNodeColumnIndex]Text = str + thisCells[treeListViewNodeColumnIndex]Text;
thisID = dr[TreeList$ViewRow$ClientID]ToString();
if (treeListViewExpendDepth > )
{
thisStyle[display] = treeListViewExpendDepth >= ConvertToInt(dr[TreeListView$Row$Depth]) ? block : none;
}
}
}
}
获取Tree的图片#region 获取Tree的图片
string GetTreeNodeImg(DataRow dr bool isLeaf bool isBottom)
{
return GetTreeNodeOtherImg(dr) + GetTreeNodeLastImg(isLeaf isBottom);
}
string GetTreeNodeOtherImg(DataRow dr)
{
if (dr[TreeListView$Row$ParentRow] != null&&!dr[TreeListView$Row$ParentRow]Equals(DBNullValue))
{
DataRow drParentRow = dr[TreeListView$Row$ParentRow] as DataRow;
bool parentIsBottom = ConvertToBoolean(drParentRow[TreeListView$Row$IsBottom]);
if (parentIsBottom)
{
return GetTreeNodeOtherImg(drParentRow) + stringFormat(<img src={} align=absmiddle> TreeListViewTreeImageFolder + whitegif);
}
else
{
return GetTreeNodeOtherImg(drParentRow) + stringFormat(<img src={} align=absmiddle> TreeListViewTreeImageFolder + igif);
}
}
else
{
return stringEmpty;
}
}
string GetTreeNodeLastImg(bool isLeaf bool isBottom)
{
//最后靠近的那个Image
string lastImg = stringEmpty;
if (isLeaf)
{
if (isBottom)
{
lastImg = stringFormat(<img src={} align=absmiddle> TreeListViewTreeImageFolder + lgif);
}
else
{
lastImg = stringFormat(<img src={} align=absmiddle>TreeListViewTreeImageFolder + tgif);
}
}
else
{
if (isBottom)
{
lastImg = stringFormat(<img src={} align=absmiddle onclick=ClickNode(thistrue\{}\); style=\cursor: hand\> TreeListViewTreeImageFolder + lminusgif thisParentParentClientID);
}
else
{
lastImg = stringFormat(<img src={} align=absmiddle onclick=ClickNode(thistrue\{}\); style=\cursor: hand\> TreeListViewTreeImageFolder + tminusgif thisParentParentClientID);
}
}
return lastImg;
}
#endregion
Js代码实现折叠效果
Code
var lExpend = lminusgif;
var lPinch = lplusgif;
var tExpend = tminusgif;
var tPinch = tplusgif;
function ClickNode(imgisBottomtableId)
{
var imgId = imgsrcsubstring(imgsrclastIndexOf(/)+);
var url = imgsrcsubstring(imgsrclastIndexOf(/)+);
var oldTrId = imgparentElementparentElementid;
var newTrId = oldTrIdsubstring(oldTrIdindexOf(_)+);
if( isBottom)
{
if( imgId == lExpend)
{
imgsrc = url+ lPinch;
imgparentElementid = lPinch;
PinchNode(newTrIdoldTrIdtableId);
}
else
{
imgsrc = url + lExpend;
imgparentElementid = lExpend;
ExpendNode(newTrIdoldTrIdtableId);
}
}
else
{
if( imgId == tExpend )
{
imgsrc = url+ tPinch;
imgparentElementid = tPinch;
PinchNode(newTrIdoldTrIdtableId);
}
else
{
imgsrc = url + tExpend;
imgparentElementid = tExpend;
ExpendNode(newTrIdoldTrIdtableId);
}
}
}
function ExpendNode(newIdoldIdtableId)
{
var tree = documentgetElementById(tableId);
for( var i = ; i < treerowslength; i++ )
{
if( treerows[i]idindexOf(newId) != && treerows[i]id != oldId )
{
var isExpend = true;
var pId = treerows[i]id;
while( pId != oldId)
{
for( var j = ; j < ; j++ )
pId = pIdsubstring( pIdlastIndexOf(/));
var parent = documentgetElementById(pId);
if( parent != null )
{
var tempId = parentcells[]id;
if( tempId == lExpend || tempId == tExpend || tempId == )
;
else
{
isExpend = false;
break;
}
}
else
break;
}
if( isExpend )
treerows[i]styledisplay=block;
}
}
}
function PinchNode(newIdoldIdtableId)
{
var tree = documentgetElementById(tableId);
for( var i = ; i < treerowslength; i++ )
{
if( treerows[i]idindexOf(newId) != && treerows[i]id != oldId)
{
treerows[i]styledisplay = none;
}
}
}