I'm trying to use the asTreeview control in my project, and being
relatively new to asp.net and especially AJAX, I'm trying to achieve
the desired result by modifying existing code (DemoServerControl)
rather than actually understanding the inner workings of the whole
thing :).
The implementation is used for basic product category browsing, and
everything works fine except the following:
I added a public SelectedValue property to my control which simply
returns the NodeValue of the selected node if one is selected or
String.Empty if nothing is selected. I also have a setter for this
property with which I am having trouble. What I want to achieve is
when the SelectedValue is set, the asTreeview should be populated with
all the nodes that are necessary to be displayed so that the desired
node is visible, and that one can still navigate the tree and perhaps
select another node. Essentially I want to place this control inside
an ASP.Net FormView's EditItemTemplate and bind a product's category
id to the SelectedValue of this control.
In addition there is a IncludePending property which simply filters
some categories from the result. I'm not having problems with this
feature.
So here is my code (most of which is identical to the
DemoServerControl.cs):
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Text;
using Geekees.Common.Controls;
using Geekees.Common.Utilities;
using ClassLibrary;
using DAL;
/// <summary>
/// Summary description for CategoryPicker
/// </summary>
namespace MyControls
{
public class CategoryPicker : WebControl
{
protected ASTreeView astvCategories;
public string SelectedValue
{
get
{
return astvCategories.GetSelectedNode() == null ?
String.Empty:
astvCategories.GetSelectedNode().NodeValue; }
set { if (value != String.Empty) ExpandAndSelect(value); }
}
// if true doesn't filter out pending categories
private bool _include_pending;
public bool Include_pending
{
get { return _include_pending; }
set { _include_pending = value; }
}
public CategoryPicker()
{
this.astvCategories = new ASTreeView();
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
InitializeControls();
}
protected override void CreateChildControls()
{
base.CreateChildControls();
this.Controls.Add(this.astvCategories);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
EnsureChildControls();
if (!this.Page.IsPostBack)
this.GenerateTree();
}
private void InitializeControls()
{
this.astvCategories.ID = "astvCategories";
this.astvCategories.EnableStripAjaxResponse = true;
this.astvCategories.BasePath = "~/scripts/astreeview/";
this.astvCategories.DataTableRootNodeValue = "0";
this.astvCategories.EnableRoot = false;
this.astvCategories.EnableNodeSelection = true;
this.astvCategories.EnableCheckbox = false;
this.astvCategories.EnableDragDrop = false;
this.astvCategories.EnableTreeLines = true;
this.astvCategories.EnableNodeIcon = false;
this.astvCategories.EnableCustomizedNodeIcon = false;
this.astvCategories.EnableContextMenu = false;
this.astvCategories.EnableDebugMode = false;
this.astvCategories.EnableAjaxOnEditDelete = false;
this.astvCategories.AddNodeProvider =
this.Page.Request.Url.GetLeftPart(UriPartial.Path); //"~/
ASTreeViewDemo/ASTreeViewDemo5.aspx";
this.astvCategories.AdditionalAddRequestParameters =
"{'t2':'ajaxAdd'}";
this.astvCategories.LoadNodesProvider =
this.Page.Request.Url.GetLeftPart(UriPartial.Path);//"~/ASTreeViewDemo/
ASTreeViewDemo5.aspx";
this.astvCategories.AdditionalLoadNodesRequestParameters =
"{'t1':'ajaxLoad'}";
}
private void GenerateTree()
{
List<Category> root_categories =
CategoryManager.GetRootCategoriesWithChildNodeCount(Include_pending);
ASTreeViewNode root = this.astvCategories.RootNode;
foreach (Category c in root_categories)
{
string catName = c.Categoryname;
string catId = c.Id.ToString();
string parentId = c.Parent_id.ToString();
int childNodesCount = (int)c.Childnodecount;
ASTreeViewLinkNode node = new
ASTreeViewLinkNode(catName, catId);
node.VirtualNodesCount = childNodesCount;
node.VirtualParentKey = catId;
node.IsVirtualNode = childNodesCount > 0;
node.NavigateUrl = "#";
//List<KeyValuePair<string, string>> attrs = new
List<KeyValuePair<string, string>>();
node.AdditionalAttributes.Add(new KeyValuePair<string,
string>("onclick", "return false;"));
//node.AdditionalAttributes = attrs;
root.AppendChild(node);
}
}
protected override void Render(HtmlTextWriter writer)
{
if (this.Page.Request.QueryString["t1"] == "ajaxLoad")
{
string virtualParentKey =
this.Page.Request.QueryString["virtualParentKey"];
List<Category> results;
if (virtualParentKey == null)
results =
CategoryManager.GetRootCategoriesWithChildNodeCount(Include_pending);
else
results =
CategoryManager.GetSubCategoriesWithChildNodeCount(UInt32.Parse(virtualParentKey),
Include_pending);
ASTreeViewNode root = new ASTreeViewNode("root");
foreach (Category c in results)
{
string catName = c.Categoryname;
string catId = c.Id.ToString();
string parentId = c.Parent_id.ToString();
int childNodesCount = (int)c.Childnodecount;
ASTreeViewLinkNode node = new
ASTreeViewLinkNode(c.Pending ? "<font style='color:red;'>" + catName +
"</font>" : catName, catId);
//ASTreeViewLinkNode node = new
ASTreeViewLinkNode(catName, catId);
node.VirtualNodesCount = childNodesCount;
node.VirtualParentKey = catId;
node.IsVirtualNode = childNodesCount > 0;
node.NavigateUrl = "#";
node.AdditionalAttributes.Add(new
KeyValuePair<string, string>("onclick", "return false;"));
root.AppendChild(node);
}
writer.Write(astvCategories.AjaxResponseStartTag);
HtmlGenericControl ulRoot = new
HtmlGenericControl("ul");
astvCategories.TreeViewHelper.ConvertTree(ulRoot,
root, false);
foreach (Control c in ulRoot.Controls)
c.RenderControl(writer);
writer.Write(astvCategories.AjaxResponseEndTag);
}
else
base.Render(writer);
}
private void PopulateNodes(List<Category> categories,
List<ASTreeViewNode> nodes)
{
foreach (Category c in categories)
{
string catName = c.Categoryname;
string catId = c.Id.ToString();
string parentId = c.Parent_id.ToString();
int childNodesCount = (int)c.Childnodecount;
ASTreeViewLinkNode node = new
ASTreeViewLinkNode(c.Pending ? "<font style='color:red;'>" + catName +
"</font>" : catName, catId);
node.VirtualNodesCount = childNodesCount;
node.VirtualParentKey = catId;
node.IsVirtualNode = childNodesCount > 0;
node.NavigateUrl = "#";
node.AdditionalAttributes.Add(new KeyValuePair<string,
string>("onclick", "return false;"));
// add new node to parent's ChildNode list
nodes.Add(node);
}
}
private void PopulateSubLevel(uint parent_id, ASTreeViewNode
parent_node)
{
List<Category> children =
CategoryManager.GetSubCategoriesWithChildNodeCount(parent_id,
Include_pending);
PopulateNodes(children, parent_node.ChildNodes);
}
private void ExpandAndSelect(string categoryId)
{
// get the path to the desired category (returns string
like 2/6/23/43)
string path =
CategoryDALC.GetCategoryPathIds(uint.Parse(categoryId));
string[] pathcompids = path.Split('/'); //split into array
of cat ids
List<ASTreeViewNode> next_tnc, tnc;
next_tnc = astvCategories.RootNode.ChildNodes; // start
with the children of root initialized in GenerateTree
foreach (string catId in pathcompids)
{
tnc = next_tnc;
foreach (ASTreeViewNode tn in tnc)
{
if (tn.NodeValue == categoryId)
{
tn.Selected = true; // if this is the desired
node set Selected
}
PopulateSubLevel(uint.Parse(tn.NodeValue), tn); //
load all children
if ((tn.NodeValue == catId) && (tn.NodeValue !=
categoryId))
{
tn.OpenState =
ASTreeViewNodeOpenState.Open; // if this node is in our path set it's
state to open
next_tnc = tn.ChildNodes; // we will process
the children of this node when done with current set
}
else
{
tn.OpenState =
ASTreeViewNodeOpenState.Close; // leave nodes not in path Closed
}
}
}
}
}
}
I don't have a problem with filling the right data into the tree, the
control displays what I expect, all necessary nodes are filled and
created, and the desired category is marked as selected. I have two
issues:
1) all branches of the tree have the little + sign next to it, even
the ones which are expanded and for which I have set
ASTreeViewNodeOpenState to Open ... perhaps something else needs to be
set ...
2) and the bigger problem, if I click on any + sign to expand a node,
it loads the entire page inside the clicked node. Obviously the AJAX
call to load nodes is getting messed up, perhaps I'm not setting some
property when adding nodes, or I just don't know at all what I'm
doing.
Any advice would be greatly appreciated, and thanks a lot if you came
this far in reading my post.
tin
The trick is in the Render method. please check the sample 5 for how
to using the dynamic loading.
Thanks.
Weijie
> 2) and the bigger problem, if I click on any + sign to expand a node,
> it loads the entire page inside the clicked node. Obviously the AJAX
> call to load nodes is getting messed up, perhaps I'm not setting some
> property when adding nodes, or I just don't know at all what I'm
> doing.
this was resolved ... the page that contained the control was doing
some QueryString checking
in Page_Load and when it found the "t1" did a redirect which was then
rendered inside the
astreeview....
tin
The loading of the entire page inside the treeview was resolved ... I
had a QueryString checking in the Page_Load
event of the page that contained the control, which did a Redirect
when it encountered the "t1"
and the result was being returned and then rendered inside the
ASTreeView ...
... now the problem remains that even though the nodes are closed, a +
sign is rendered and if
I click on it, another set of child nodes gets loaded and added so I
have 2 copies of each child,
although I added them server-side when the setter property was
called ...
tin
The loading of the entire page inside the treeview was resolved ... I