asp.net + How to create custom multi-templated tree databound control?
I dont want to use asp.net's TreeView control. I want to create a custom template databound control with multi template support like -
<asp:MtNavigationControl>
<ItemTemplate>
...
...
</ItemTemplate>
<SelectedItemTemplate>
...
...
</SelectedItemTemplate>
<ParentItemTemplate>
...
...
</ParentSelectedItemTemplate>
<SelectedParentItemTemplate>
...
...
</SelectedParentSelectedItemTemplate>
</asp:MtNavigationControl>
My data is like -
class Employee
{
string EmployeeName
List<Employee> Employees
}
Does anyone know how to accomplish it? Please help开发者_JAVA百科 !!!
Damn, I thought I might have found what I was looking for. I have the same question and I have it NEARLY complete. I am not sure if it is my class (TreeBranches) or the below class. Seems to work great on the initial render. But then each postback it seems to render things twice. I have tried things like Controls.Clear() but the .UniqueID's seem to always be for a second set of control.
Basically, my TreeBranches is just a collection class for Branch objects. Quite similar to your Employee example. The Template is nothing more than the following:
<h2><a href='<%= this.NavigationUrl %>'><%= this.Title %></a></h2>
<asp:PlaceHolder ID="phContents" runat="server" EnableViewState="true"></asp:PlaceHolder>
It will generate a UL with LI's below them. And if there is a nested Branch, a new UL will be contained in the LI that is the parent. This can be as deep as possible.
using System; using System.Collections.Generic; using System.Linq; using System.Web.UI; using System.Web.UI.WebControls; using System.Text; using System.ComponentModel; using System.Collections;
namespace Website.Controls { public partial class 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
}
精彩评论