该死,我以为我可能找到了我要找的东西。我有同样的问题,我几乎完成了。我不确定它是我的班级(TreeBranches)还是下面的班级。似乎在初始渲染上效果很好。但是每次回发似乎都会渲染两次。我尝试过 Controls.Clear() 之类的方法,但 .UniqueID 似乎总是用于第二组控件。
基本上,我的 TreeBranches 只是 Branch 对象的集合类。与您的 Employee 示例非常相似。模板无非如下:
<h2><a href='<%= this.NavigationUrl %>'><%= this.Title %></a></h2>
<asp:PlaceHolder ID="phContents" runat="server" EnableViewState="true"></asp:PlaceHolder>
它会生成一个带有 LI 的 UL。如果存在嵌套分支,则新的 UL 将包含在作为父级的 LI 中。这可以尽可能深。
使用系统;
使用 System.Collections.Generic;
使用 System.Linq;
使用 System.Web.UI;
使用 System.Web.UI.WebControls;
使用 System.Text;
使用 System.ComponentModel;
使用 System.Collections;
命名空间 Website.Controls {
公共部分类 HeirarchicalList : System.Web.UI.UserControl {
private ITemplate _layoutTemplate = null;
private ITemplate _itemTemplate = null;
private string _LayoutPlaceholderID = "";
#region Public Properties
public TreeBranches DataSource { get; set; }
/// <summary>
/// Gets or Sets the Header for this controls <h2> element.
/// </summary>
[PersistenceMode(PersistenceMode.Attribute)]
public string Title { get; set; }
/// <summary>
/// Gets or Sets the Class name for the outermost LayoutTemplate item.
/// </summary>
[PersistenceMode(PersistenceMode.Attribute)]
public string RootClass { get; set; }
/// <summary>
/// Gets or Sets the Headers link for this controls <h2> element.
/// </summary>
[PersistenceMode(PersistenceMode.Attribute)]
public string NavigationUrl { get; set; }
/// <summary>
/// Gets or Sets the local ID for the LayoutTemplates Placeholder control. Defaults to "layoutPlaceholder"
/// </summary>
[PersistenceMode(PersistenceMode.Attribute)]
public string LayoutPlaceholderID {
get { return string.IsNullOrWhiteSpace(this._LayoutPlaceholderID) ? "layoutPlaceholder" : this._LayoutPlaceholderID; }
set { this._LayoutPlaceholderID = value; }
}
[Browsable(false)]
[DefaultValue(null)]
[TemplateContainer(typeof(LayoutContainer))]
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate LayoutTemplate {
get { return _layoutTemplate; }
set { _layoutTemplate = value; }
}
[Browsable(false)]
[DefaultValue(null)]
[TemplateContainer(typeof(ItemContainer))]
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate ItemTemplate {
get { return _itemTemplate; }
set { _itemTemplate = value; }
}
#endregion Public Properties
public override void DataBind() {
if ((_itemTemplate != null) && (_layoutTemplate != null)) {
if (this.phContents.HasControls())
this.phContents.Controls.Clear(); // Clear any existing child controls.
LayoutContainer parent = new LayoutContainer(this.RootClass); // Apply the RootClass only to the Root item
_layoutTemplate.InstantiateIn(parent);
PlaceHolder ph = parent.FindControl(this.LayoutPlaceholderID) as PlaceHolder;
if (ph == null)
throw new FormatException(string.Format("Unable to find the LayoutTemplate's PlaceHolder object. Either one does not exist or the name {0} specified in the LayoutPlaceholderID does not match the ID of the PlaceHolder.", this.LayoutPlaceholderID));
this.RecurseBranches(this.DataSource.ToList(), ph);
this.phContents.Controls.Add(parent);
} else {
throw new FormatException("Both the LayoutTemplate and the ItemTemplate must be defined.");
} // if the template has been defined
base.DataBind();
}
/// <summary>
/// This method will take the List of Branches and generate an unordered list with however many branches are necessary.
/// </summary>
/// <param name="Branches"></param>
/// <param name="Canvas"></param>
private void RecurseBranches(List<Branch> Branches, Control Canvas) {
foreach (Branch branch in Branches) {
ItemContainer SingleItem = new ItemContainer(branch);
_itemTemplate.InstantiateIn(SingleItem);
if (branch.HasChildren) {
LayoutContainer NewGroup = new LayoutContainer(); // Notice no RootClass being passed in here
_layoutTemplate.InstantiateIn(NewGroup);
PlaceHolder NewCanvas = NewGroup.FindControl(this.LayoutPlaceholderID) as PlaceHolder;
PlaceHolder Parent = SingleItem.FindControl(this.LayoutPlaceholderID) as PlaceHolder;
this.RecurseBranches(branch.Children.ToList(), NewCanvas); // Add new Items to the Group
Parent.Controls.Add(NewGroup); // Add the new Group to its Parent Item
} // if there are any children to go under this node
Canvas.Controls.Add(SingleItem); // Add the current Item to the Canvas
} // foreach of the Branches to bind
} // RecurseBranches - Method
} // HeirarchicalList - Class
#region Container Classes
public class LayoutContainer : Control, INamingContainer {
public string RootClass { get; set; }
internal LayoutContainer() { }
internal LayoutContainer(string RootClass) {
this.RootClass = RootClass;
} // LayoutContainer - Constructor
} // LayoutContainer - Class
public class ItemContainer : Control, INamingContainer {
public Branch BranchItem { get; set; }
internal ItemContainer(Branch BranchItem) {
this.BranchItem = BranchItem;
} // ItemContainer - Constructor
} // ItemContainer - Class
#endregion
}