您的位置:首页 > 产品设计 > UI/UE

自定义通用System.Web.UI.IHierarchicalDataSource简单实现

2006-02-23 15:41 465 查看
什么是IHierarchicalDataSource接口呢?该接口是Asp.Net2.0中心定义的一个专用于描述一类有继承体系关系的数据的数据源,它可以作为TreeView,SiteMap等这些能够描述继承体系结构的控件的数据源。因为很多情况下,我们需要在TreeView这样的控件中显示我们的自定义数据,不适用数据邦定的情况下,我们当然也能手工来编码,坦率地说,代码也不太难写,几个递归函数而已,但是如果很多页面都用treeview的话是不是该抽象一下呢?如果使用IHierarchicalDataSource数据源,不写一条代码,就能将数据邦定到控件。本文给出的就是一个IHierarchicalDataSource接口的通用简单实现。

设计目标

我们的设计目标很明确,就是一个IHierarchicalDataSource实现,该实现类可以接受一组用户获取继承体系中的数据的函数的delegate作为构造函数的参数。

基本的delegate定义和构造函数定义如下:

//delegates
public delegate object[] GetRootItemsHandler();    //获取顶层元素
public delegate object[] GetNonRootItemsHandler(string parentId);    //获取非顶层元素
public delegate object GetItemHandler(string id);    //通过id获取元素
public delegate string GetItemIdHandler(object obj);    //通过元素获取id

//constructor
public SimpleHierarchicalDataSource(GetItemHandler itemHandler, GetItemIdHandler itemIdHandler, GetRootItemsHandler rootHandler, GetNonRootItemsHandler nonRootHandler);

简单说明一下为什么定义了这四个delegate。

首先出于通用型,元素的id使用了string类型,因为不是所有元素的id都是数值。其次,GetRootItemsHandler用于获取继承体系顶层的元素,也就是没有父元素的元素。GetNonRootItemsHandler和GetRootItemsHandler返回元素类型可以是不一样的。例如,Root Item可以是Project,而Nonroot Item可以是和project相关的requirement;当然,两者返回的元素也可以一样,比如多级产品分类。

而后两个delegate则分别用来获得元素及其id。这里的id除了作为获取元素的标识,还有一些特殊的用处。以TreeView为例,它的FindNode函数可以通过一个查询字符串来查询继承体系中的元素。例如:/1/12/45标识继承体系中id为1的元素下的id为12的元素下的id为45的元素。

代码实现

好了,闲话少说,看看实现代码吧,还是要实现好几个接口和抽象类的~~


using System;


using System.Collections;


using System.Collections.Generic;


using System.Text;




namespace Ilungasoft.Framework.Web.UI






{


    public delegate object[] GetRootItemsHandler();




    public delegate object[] GetNonRootItemsHandler(string parentId);




    public delegate object GetItemHandler(string id);




    public delegate string GetItemIdHandler(object obj);




    public class HierarchyData : System.Web.UI.IHierarchyData




    

{




        Private Members#region Private Members




        private object obj;


        private GetItemIdHandler itemIdHandler;


        private GetNonRootItemsHandler handler;


        private object parentObj;


        private string parentPath;


        private object[] childObjs;




        #endregion






        Constructors#region Constructors




        public HierarchyData(object parentObj, string parentPath, object obj, GetItemIdHandler itemIdHandler, GetNonRootItemsHandler handler)




        

{


            this.parentObj = parentObj;


            this.parentPath = parentPath;


            this.obj = obj;


            this.itemIdHandler = itemIdHandler;


            this.handler = handler;


            childObjs = handler(itemIdHandler(obj));


        }




        #endregion






        IHierarchyData Members#region IHierarchyData Members




        public System.Web.UI.IHierarchicalEnumerable GetChildren()




        

{


            return new HierarchicalCollection(parentObj, parentPath, handler(itemIdHandler(obj)), itemIdHandler, handler);


        }




        public System.Web.UI.IHierarchyData GetParent()




        

{


            string[] pathSplits = parentPath.Trim(' ', '/').Split('/');


            if (pathSplits != null && pathSplits.Length > 0)




            

{


                if (pathSplits.Length > 1)




                

{


                    string parentParentPath = "";


                    for (int i = 0; i < pathSplits.Length - 1; i++)




                    

{


                        parentParentPath = parentParentPath + "/" + pathSplits[i];


                    }


                    return new HierarchyData(itemIdHandler(pathSplits[pathSplits.Length - 2]), parentParentPath, parentObj, itemIdHandler, handler);


                }


            }


            return null;


        }




        public bool HasChildren




        

{


            get




            

{


                return childObjs != null && childObjs.Length > 0;


            }


        }




        public object Item




        

{


            get




            

{


                return obj;


            }


        }




        public string Path




        

{


            get




            

{


                return string.Format("{0}/{1}", parentPath, itemIdHandler(obj));


            }


        }




        public string Type




        

{


            get




            

{


                return obj.GetType().ToString();


            }


        }




        #endregion


    }




    public class HierarchicalCollection : System.Web.UI.IHierarchicalEnumerable




    

{




        Private Members#region Private Members




        private object parentObj;


        private string parentPath;


        private object[] objs;


        private GetItemIdHandler itemIdHandler;


        private GetNonRootItemsHandler nonRootHandler;




        #endregion


        




        Constructors#region Constructors




        public HierarchicalCollection(object parentObj, string parentPath, object[] objs, GetItemIdHandler itemIdHandler, GetNonRootItemsHandler nonRootHandler)




        

{


            this.parentObj = parentObj;


            this.parentPath = parentPath;


            this.objs = objs;


            this.itemIdHandler = itemIdHandler;


            this.nonRootHandler = nonRootHandler;


        }




        #endregion






        IHierarchicalEnumerable Members#region IHierarchicalEnumerable Members




        public System.Web.UI.IHierarchyData GetHierarchyData(object enumeratedItem)




        

{


            return new HierarchyData(parentObj, parentPath, enumeratedItem, itemIdHandler, nonRootHandler);


        }




        #endregion






        IEnumerable Members#region IEnumerable Members




        public System.Collections.IEnumerator GetEnumerator()




        

{


            return objs.GetEnumerator();


        }




        #endregion


    }




    public class RootHierarchicalDataSourceView : System.Web.UI.HierarchicalDataSourceView




    

{




        Private Members#region Private Members




        private GetItemIdHandler itemIdHandler;


        private GetRootItemsHandler rootHandler;


        private GetNonRootItemsHandler nonRootHandler;




        #endregion






        Constructors#region Constructors




        public RootHierarchicalDataSourceView(GetItemIdHandler itemIdHandler, GetRootItemsHandler rootHandler, GetNonRootItemsHandler nonRootHandler)




        

{


            this.itemIdHandler = itemIdHandler;


            this.rootHandler = rootHandler;


            this.nonRootHandler = nonRootHandler;


        }




        #endregion






        Overriden Members#region Overriden Members




        public override System.Web.UI.IHierarchicalEnumerable Select()




        

{


            return new HierarchicalCollection(null, null, rootHandler(), itemIdHandler, nonRootHandler);


        }




        #endregion


    }




    public class NonRootHierarchicalDataSourceView : System.Web.UI.HierarchicalDataSourceView




    

{




        Private Members#region Private Members




        private string parentPath;


        private GetItemHandler itemHandler;


        private GetItemIdHandler itemIdHandler;


        private GetNonRootItemsHandler nonRootHandler;


        private object parentObj;




        #endregion






        Constructors#region Constructors




        public NonRootHierarchicalDataSourceView(string parentPath, GetItemHandler itemHandler, GetItemIdHandler itemIdHandler, GetNonRootItemsHandler nonRootHandler)




        

{


            this.parentPath = parentPath;


            this.itemHandler = itemHandler;


            this.itemIdHandler = itemIdHandler;


            this.nonRootHandler = nonRootHandler;




            string[] pathSplits = parentPath.Trim(' ', '/').Split('/');


            if (pathSplits != null && pathSplits.Length > 0)




            

{


                parentObj = itemHandler(pathSplits[pathSplits.Length - 1]);


            }


        }




        #endregion






        Overriden Members#region Overriden Members




        public override System.Web.UI.IHierarchicalEnumerable Select()




        

{


            return new HierarchicalCollection(parentObj, parentPath, nonRootHandler(itemIdHandler(parentObj)), itemIdHandler, nonRootHandler);


        }




        #endregion


    }




    public class SimpleHierarchicalDataSource : System.Web.UI.IHierarchicalDataSource




    

{




        Private Members#region Private Members




        private GetItemHandler itemHandler;


        private GetItemIdHandler itemIdHandler;


        private GetRootItemsHandler rootHandler;


        private GetNonRootItemsHandler nonRootHandler;




        #endregion






        Constructors#region Constructors




        public SimpleHierarchicalDataSource(GetItemHandler itemHandler, GetItemIdHandler itemIdHandler, GetRootItemsHandler rootHandler, GetNonRootItemsHandler nonRootHandler)




        

{


            this.itemHandler = itemHandler;


            this.itemIdHandler = itemIdHandler;


            this.rootHandler = rootHandler;


            this.nonRootHandler = nonRootHandler;




            if (DataSourceChanged != null)




            

{


                //null is ok


            }


        }




        #endregion






        IHierarchicalDataSource Members#region IHierarchicalDataSource Members




        public event EventHandler DataSourceChanged;




        public System.Web.UI.HierarchicalDataSourceView GetHierarchicalView(string viewPath)




        

{


            if (viewPath == null || (viewPath != null && (viewPath.Trim().Equals("/") || viewPath.Trim().Equals(""))))




            

{


                return new RootHierarchicalDataSourceView(itemIdHandler, rootHandler, nonRootHandler);


            }


            else




            

{


                return new NonRootHierarchicalDataSourceView(viewPath, itemHandler, itemIdHandler, nonRootHandler);


            }


        }




        #endregion






        Sample Client Handlers#region Sample Client Handlers




        //public class EntityWrapper<T>


        //{


        //    public T Target;




        //    public EntityWrapper(T obj)


        //    {


        //        Target = obj;


        //    }




        //    public override string ToString()


        //    {


        //        if (typeof(T) == typeof(Entity.Project))


        //        {


        //            return StrongTyped<Entity.Project>(Target).Title;


        //        }


        //        else


        //        {


        //            return StrongTyped<Entity.Requirement>(Target).Title;


        //        }


        //    }


        //}




        //private object[] GetProjects()


        //{


        //    Entity.Project[] projects = Facade.SelectAll<Entity.Project>();


        //    if (projects != null && projects.Length > 0)


        //    {


        //        object[] objs = new object[projects.Length];


        //        for (int i = 0; i < objs.Length; i++)


        //        {


        //            objs[i] = new EntityWrapper<Entity.Project>(projects[i]);


        //        }


        //        return objs;


        //    }


        //    return null;


        //}




        //private object[] GetRequirements(string parentId)


        //{


        //    Entity.Requirement[] reqs;


        //    if (parentId.StartsWith("p"))


        //    {


        //        reqs = Facade.Select<Entity.Requirement>("ParentID = 0 and ProjectID = @ProjectID", int.Parse(parentId.TrimStart('p')));


        //    }


        //    else


        //    {


        //        reqs = Facade.Select<Entity.Requirement>("ParentID = @ParentID", int.Parse(parentId.TrimStart('r')));


        //    }


        //    if (reqs != null && reqs.Length > 0)


        //    {


        //        object[] objs = new object[reqs.Length];


        //        for (int i = 0; i < objs.Length; i++)


        //        {


        //            objs[i] = new EntityWrapper<Entity.Requirement>(reqs[i]);


        //        }


        //        return objs;


        //    }


        //    return null;


        //}




        //private object GetProjectOrRequirement(string id)


        //{


        //    if (id.StartsWith("p"))


        //    {


        //        return new EntityWrapper<Entity.Project>(Facade.Get<Entity.Project>(int.Parse(id.TrimStart('p'))));


        //    }


        //    else


        //    {


        //        return new EntityWrapper<Entity.Requirement>(Facade.Get<Entity.Requirement>(int.Parse(id.TrimStart('p'))));


        //    }


        //}




        //private string GetProjectOrRequirementId(object obj)


        //{


        //    if (obj is EntityWrapper<Entity.Project>)


        //    {


        //        return "p" + StrongTyped<EntityWrapper<Entity.Project>>(obj).Target.ID.ToString();


        //    }


        //    else


        //    {


        //        return "r" + StrongTyped<EntityWrapper<Entity.Requirement>>(obj).Target.ID.ToString();


        //    }


        //}




        #endregion


    }


}
注意代码中最后一个#region SampleClientHandler是一组project-requirement两种元素的继承体系的delegate实现范例。

使用的时候,只要将这几个delegate实现函数引用作为构造函数的参数,将实例化的datasource赋给treeview的datasource,就能轻松显示整个继承体系的元素了。

源码下载

HierarchicalDataSource.zip

--

以上代码虽然具有一定的通用性,但是本身毕竟是为了一定的特殊用途而写,因此功能并不完备,如果要大量使用,请酌情重构和改写。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐