Several people have noticed that the kit's TreeView adapter doesn't presently offer any postback capabilities. Likewise, it's been noted that the adapted TreeView doesn't distinguish when a node is in a "selected" state. I think several people have been
thinking about how to solve this. While we await those contributions, I thought I'd share what small progress I've made while thinking about this problem over the past several days.
I've included (below) the code for a new (research-quality) version of TreeViewAdapter (C# only). I've also included a page (single ASPX file) meant to demonstrate some of the features of this enhanced TreeView adapter.
Note:
You can control (to some degree) the rendering technique (adapter or not) used for an individual TreeView by setting its new expando property, EnableCssFriendlyAdapter, to false. The default is true.
There is a new class, AspNet-TreeView-Selected, that decorates whatever TreeNode is in the selected state.
There is some super-experimental code that is commented out in RaisePostBackEvent (in TreeViewAdapter.cs). It will only work in a fully trusted web app so it isn't safe or recommended for general use. Those who are curious can play with this code by uncommenting
it and running it under VWD/Cassini locally in the normally trusted environment that that configuration provides.
As you play with this new code, try temporarily removing the TreeView-related elements from the site's .browser file. That way you'll see what the completely unadapted framework response is like. Notice that the server-side events like SelectedNodeChanged
always fire properly in this native (unadapted) configuration. Yet, this same event won't fire (unless you uncomment the super-experimental, high-trust code) even if you set EnableCssFriendlyAdapter to false. That's obviously a huge problem but right now
I don't see a way to get the server-side event processing to happen. We need to work on this; feel free to post solutions if you play around with this code and get it to work better.
In general, I'd love some feedback on this new adapter.
I know this is a rather long and complex posting. Still, I know that several people were anxiously awaiting progress on the TreeView adapter so I'm hoping that folks will test out this experimental version of the adapter. Any feedback yet?
I know this is a rather long and complex posting. Still, I know that several people were anxiously awaiting progress on the TreeView adapter so I'm hoping that folks will test out this experimental version of the adapter. Any feedback yet?
is there any way you can make a download for us? for example, a zip file of everything we need to test this out, including the folder structure and files so that all we need to do is unzip it to our iis folder? i'll admit that making a new site and having
to copy/paste all that is a bit daunting.
[the reason i personally haven't really looked into it (other than the daunting part) is because the features you've added don't really apply to me and were requested by others. the two things i was interested in were keeping the current path expanded and
"active" classing the entire path to the current node, but i've gotten those working on my own.]
hmm. one thing i'm confused about here is this -- cj and i both were able to get the selected node working before (http://forums.asp.net/thread/1313584.aspx)... the only difference
in my situation now is that i'm trying it with an XMLdatasource instead of the sitemap datasource (see
http://forums.asp.net/thread/1321336.aspx). would that make a difference somehow?
OK, maybe I'm confused a bit, too. Ha ha. It seemed like you were asking (in
http://forums.asp.net/thread/1321336.aspx) why postback wasn't ending up calling your SelectedNodeChanged event handler. This thread explains that this (and potentially other) postback event handlers
are being twarted by design limitations deep in the .Net framework. I'm working with the ASP.NET team to try to work around this so server-side events like SelectedNodeChanged are called upon postback regardless of whether or not adapters are present in the
web site.
I think what you and cj did was to modify your version of the adapter so it distinguished the selected state of a node using CSS. That's great and the next rev of the adapters should do the same thing. But whether or not postback event handlers are called
on the server is a separate matter.
I don't mean to get on a rant about postbacks and events and such. Can you help me understand better the connection between your question about using an XmlDataSource and your post
http://forums.asp.net/thread/1321336.aspx that discusses postback event handler problems.
I'm betting we can fix any problems having to do with using an XmlDataSource rather than a site map data source. But getting the postback events to fire while the adapters are in play may be something we have to defer for the moment.
okay, sorry, i see how i might have sent you in the wrong direction. the reason i got onto the postback thing was because the treeview wasn't working the same way with the XMLdatasource and i was trying to see if i could get the selectedNode information...
in case there was another way to set the styles of the nodes... maybe...
so, to step back... my problem is this - i have three areas of the site with different navigation needs:
main navigation, which is great and using the sitemap source and the treeview adapter
admin navigation -- which i don't want displayed in the public sitemap
blog navigation -- which will need to be dynamic as the archive grows, doesn't have to be in public sitemap
i figured i could get #2 to work as #1 is working just by populating the admin treeview with XML instead of the web.sitemap. this would keep these links out of my public sitemap. i've also seen ways to create the XML from a database and/or dynamically, so
i figured that would solve #3, but also wouldnt' be using the sitemap datasource.
so, i implemented the admin navigation using XML. because the structure was slightly different than the main navigation, i adjusted the CSS for this area and it displays and rolls over fine. however, if you click on a nav item (which has a URL, so the page
does refresh), that nav item doesn't show the selected state as is does on my #1 nav. that is, when i look at the source code i can see that the CSS style is the same as all the others.
going back to the adapter cs, that makes me wonder why it's not triggering the item.Selected == true conditionals or any of cj's isActivePath conditionals. that's why i was wondering if there was anything about using the sitemap datasource made the adapter
function differently. it doesn't seem that it should, so i'm hoping that i'm just overlooking something here. it would really solve a lot of my problems here (i think) if i could get this to work in the same fashion.
i'll keep plugging away at it, but if you have any thoughts, i do appreciate them!
Look at the original version of the kit's web.config and the TreeView sample aspx. You'll see that the web.config sets up multiple site maps. What you do is to add entries in your web.config that point to different files that use the sitemap format. Then
you refer to those sitemap providers specifically in your SiteMapDataSource. So you can always simply pair your TreeView with a SiteMapDataSource if you like. The same is true for Menus, etc. You don't have to roll your own XML if you don't want to.
That said, if you did roll your own XML for the TreeView so you could bind it to an XmlDataSource it still ought to work because the TreeView (and its adapter) doesn't know or or care about where its data comes from. At least, that's the intent.
If this isn't working for you, with XmlDataSources, I need you to post some of your code so I can look more closely at what you are doing.
okay, i decided not to "roll my own" XML for the admin nav. :) so, i'm using the two different sitemap sources via the web.config and web.sitemap (which holds the two).
i still don't know why the XML wasn't working correctly, but will have to hold off on that for now. i'll see how the blog nav works and post back about how that goes, for better or worse. :)
Having encountered a performance problem with IE and a nested version of the out of the box Treeview control (my masterpage has a few tables and as a result, a 181 node treeview takes roughly 5 seconds to render) I started playing with the CSS friendly version.
The CSS friendly version fixes my problem, and before finding your solution for postbacks and selected node, I managed to reverse engineer the same thing (thank God for Reflector!).
My problem is that the tree doesn't remember its state between postbacks. I can't seem to hack this into working, and haven't found a way to make it work yet.
I'm going to keep trying, but any thoughts you have in the meantime would be appreciated.
Hi Dan, I'd like to try to help. I've been working a lot on the TreeView adapter since I posted the version shown above. It still encompasses much of what you see above but now includes a few other things (and some of the code shown above has been cleaned
up, refactored, renamed, etc.). I don't want post all of those changes/updates yet so I'm going to try to give you instructions for how you can do some surgical enhancements to the code shown above to begin to achieve a rudimentary but (in my opinion) effective
re-expansion functionality with your TreeView.
My premise is simple: in many cases the end user is only interested in having the tree re-expand to show their selected node. They don't really care to see the expansion of other parts of the tree that they may have been exploring before selecting a node.
In these cases, you can achieve that behavior with a simple modification to the adapter (shown below). That said, I do realize that this re-expansion methodology isn't going to satisfy everyone. But I need to take things one step at a time layering in better
and better functionality.
So, here is what I would suggest you do to enhance your TreeView adapter for now...
Start with the adapter code shown above. Find the call to AssureAllNodesAreBuilt in RenderContents. Immediately after that call, add another method call to a new method you'll write called ExpandToSelectedNode(). Here is it's code:
private void ExpandToSelectedNode()
{
TreeView treeView = Control as TreeView;
if ((treeView != null) && (treeView.SelectedNode != null))
{
treeView.CollapseAll();
TreeNode nodeToExpand = treeView.SelectedNode.Parent;
while (nodeToExpand != null)
{
nodeToExpand.Expanded = true;
nodeToExpand = nodeToExpand.Parent;
}
}
}
Would you give that a shot and let me know what you think?
Russ Helfand
Contributor
3304 Points
744 Posts
Experimental TreeView adapter version: with postback and node selection
May 24, 2006 02:26 PM|LINK
Several people have noticed that the kit's TreeView adapter doesn't presently offer any postback capabilities. Likewise, it's been noted that the adapted TreeView doesn't distinguish when a node is in a "selected" state. I think several people have been thinking about how to solve this. While we await those contributions, I thought I'd share what small progress I've made while thinking about this problem over the past several days.
I've included (below) the code for a new (research-quality) version of TreeViewAdapter (C# only). I've also included a page (single ASPX file) meant to demonstrate some of the features of this enhanced TreeView adapter.
Note:
As you play with this new code, try temporarily removing the TreeView-related elements from the site's .browser file. That way you'll see what the completely unadapted framework response is like. Notice that the server-side events like SelectedNodeChanged always fire properly in this native (unadapted) configuration. Yet, this same event won't fire (unless you uncomment the super-experimental, high-trust code) even if you set EnableCssFriendlyAdapter to false. That's obviously a huge problem but right now I don't see a way to get the server-side event processing to happen. We need to work on this; feel free to post solutions if you play around with this code and get it to work better.
In general, I'd love some feedback on this new adapter.
**************** TreeViewAdapter.cs *********************
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Reflection; namespace CSSFriendly { public class TreeViewAdapter : System.Web.UI.WebControls.Adapters.HierarchicalDataBoundControlAdapter, IPostBackEventHandler { protected bool EnableCssFriendlyAdapter { get { bool bReturn = true; // normally the adapters are enabled // Individual controls can use the expando property called EnableCssFriendlyAdapter // as a way to turn the adapters off. // if ((Control != null) && (Control.Attributes["EnableCssFriendlyAdapter"] != null) && (Control.Attributes["EnableCssFriendlyAdapter"].Length > 0) && (Control.Attributes["EnableCssFriendlyAdapter"].IndexOf("false", StringComparison.OrdinalIgnoreCase) == 0)) { bReturn = false; } return bReturn; } } public TreeViewAdapter() { // } // Implementation of IPostBackEventHandler public void RaisePostBackEvent(string eventArgument) { /* TreeView treeView = Control as TreeView; IPostBackEventHandler handler = Control as IPostBackEventHandler; if ((handler != null) && (treeView != null)) { FieldInfo field = treeView.GetType().GetField("_adapter", BindingFlags.NonPublic | BindingFlags.Instance); if (field != null) { object oldValue = field.GetValue(treeView); field.SetValue(treeView, null); handler.RaisePostBackEvent(eventArgument); field.SetValue(treeView, oldValue); } } */ TreeView treeView = Control as TreeView; if ((treeView != null) && (eventArgument != null) && eventArgument.StartsWith("s")) { string selectedNodeValuePath = eventArgument.Substring(1).Replace("\\", "/"); TreeNode selectedNode = treeView.FindNode(selectedNodeValuePath); if ((selectedNode != null) && (treeView.SelectedNode != selectedNode)) { selectedNode.Selected = true; } } } protected override void OnInit(EventArgs e) { base.OnInit(e); if (EnableCssFriendlyAdapter) { RegisterScripts(); } } private void RegisterScripts() { Utility.RegisterScripts(Page); Page.ClientScript.RegisterClientScriptInclude(GetType(), GetType().ToString(), Page.ResolveUrl("~/JavaScript/TreeViewAdapter.js")); } protected override void RenderBeginTag(HtmlTextWriter writer) { if (EnableCssFriendlyAdapter) { if ((Control != null) && (Control.Attributes["CssSelectorClass"] != null) && (Control.Attributes["CssSelectorClass"].Length > 0)) { writer.WriteLine(); writer.WriteBeginTag("div"); writer.WriteAttribute("class", Control.Attributes["CssSelectorClass"]); writer.Write(HtmlTextWriter.TagRightChar); writer.Indent++; } writer.WriteLine(); writer.WriteBeginTag("div"); writer.WriteAttribute("class", "AspNet-TreeView"); writer.Write(HtmlTextWriter.TagRightChar); } else { base.RenderBeginTag(writer); } } protected override void RenderEndTag(HtmlTextWriter writer) { if (EnableCssFriendlyAdapter) { writer.WriteEndTag("div"); if ((Control != null) && (Control.Attributes["CssSelectorClass"] != null) && (Control.Attributes["CssSelectorClass"].Length > 0)) { writer.Indent--; writer.WriteLine(); writer.WriteEndTag("div"); } writer.WriteLine(); } else { base.RenderEndTag(writer); } } protected override void RenderContents(HtmlTextWriter writer) { if (EnableCssFriendlyAdapter) { TreeView treeView = Control as TreeView; if (treeView != null) { AssureAllNodesAreBuilt(treeView); writer.Indent++; BuildItems(treeView.Nodes, true, true, writer); writer.Indent--; writer.WriteLine(); } } else { base.RenderContents(writer); } } private void BuildItems(TreeNodeCollection items, bool isRoot, bool isExpanded, HtmlTextWriter writer) { if (items.Count > 0) { writer.WriteLine(); writer.WriteBeginTag("ul"); if (!isExpanded) { writer.WriteAttribute("class", "AspNet-TreeView-Hide"); } writer.Write(HtmlTextWriter.TagRightChar); writer.Indent++; foreach (TreeNode item in items) { BuildItem(item, writer); } writer.Indent--; writer.WriteLine(); writer.WriteEndTag("ul"); } } private void BuildItem(TreeNode item, HtmlTextWriter writer) { TreeView treeView = Control as TreeView; if ((treeView != null) && (item != null) && (writer != null)) { writer.WriteLine(); writer.WriteBeginTag("li"); writer.WriteAttribute("class", GetNodeClass(item)); writer.Write(HtmlTextWriter.TagRightChar); writer.Indent++; writer.WriteLine(); if (item.ChildNodes.Count > 0) { writer.WriteBeginTag("span"); writer.WriteAttribute("class", ((item.Expanded == true) ? "AspNet-TreeView-Collapse" : "AspNet-TreeView-Expand")); writer.WriteAttribute("onclick", "ExpandCollapse__AspNetTreeView(this)"); writer.Write(HtmlTextWriter.TagRightChar); writer.Write(" "); writer.WriteEndTag("span"); writer.WriteLine(); } if ((item.NavigateUrl.Length > 0) || (item.SelectAction == TreeNodeSelectAction.Select)) { writer.WriteBeginTag("a"); if (item.NavigateUrl.Length > 0) { writer.WriteAttribute("href", Page.Server.HtmlEncode(Page.ResolveUrl(item.NavigateUrl))); } else { writer.WriteAttribute("href", Page.ClientScript.GetPostBackClientHyperlink(treeView, "s" + (Page.Server.HtmlEncode(item.ValuePath)).Replace("/", "\\"), true)); } if (item.Target.Length > 0) { writer.WriteAttribute("target", item.Target); } if (item.ToolTip.Length > 0) { writer.WriteAttribute("title", item.ToolTip); } else if (treeView.ToolTip.Length > 0) { writer.WriteAttribute("title", treeView.ToolTip); } writer.Write(HtmlTextWriter.TagRightChar); writer.Indent++; writer.WriteLine(); } else { writer.WriteBeginTag("span"); if (item.ChildNodes.Count > 0) { writer.WriteAttribute("class", "AspNet-TreeView-ClickableNonLink"); writer.WriteAttribute("onclick", "ExpandCollapse__AspNetTreeView(this.parentNode.getElementsByTagName('span')[0])"); } else { writer.WriteAttribute("class", "AspNet-TreeView-NonLink"); } writer.Write(HtmlTextWriter.TagRightChar); writer.Indent++; writer.WriteLine(); } string imgSrc = GetImageSrc(treeView, item); if (imgSrc.Length > 0) { writer.WriteBeginTag("img"); writer.WriteAttribute("src", Page.ResolveUrl(imgSrc)); writer.WriteAttribute("alt", item.ToolTip.Length > 0 ? item.ToolTip : (treeView.ToolTip.Length > 0 ? treeView.ToolTip : item.Text)); writer.Write(HtmlTextWriter.SelfClosingTagEnd); } writer.Write(item.Text); if ((item.NavigateUrl.Length > 0) || (item.SelectAction == TreeNodeSelectAction.Select)) { writer.Indent--; writer.WriteLine(); writer.WriteEndTag("a"); } else { writer.Indent--; writer.WriteLine(); writer.WriteEndTag("span"); } if ((item.ChildNodes != null) && (item.ChildNodes.Count > 0)) { BuildItems(item.ChildNodes, false, (item.Expanded == true), writer); } writer.Indent--; writer.WriteLine(); writer.WriteEndTag("li"); } } private string GetNodeClass(TreeNode item) { string value = "AspNet-TreeView-Leaf"; if (item != null) { if (item.Depth == 0) { if (item.ChildNodes.Count > 0) { value = "AspNet-TreeView-Root"; } else { value = "AspNet-TreeView-Root AspNet-TreeView-Leaf"; } } else if (item.ChildNodes.Count > 0) { value = "AspNet-TreeView-Parent"; } if (item.Selected) { value += " AspNet-TreeView-Selected"; } } return value; } private string GetImageSrc(TreeView treeView, TreeNode item) { string imgSrc = ""; if ((treeView != null) && (item != null)) { imgSrc = item.ImageUrl; if (imgSrc.Length == 0) { if (item.Depth == 0) { if ((treeView.RootNodeStyle != null) && (treeView.RootNodeStyle.ImageUrl.Length > 0)) { imgSrc = treeView.RootNodeStyle.ImageUrl; } } else { if (item.ChildNodes.Count == 0) { if ((treeView.LeafNodeStyle != null) && (treeView.LeafNodeStyle.ImageUrl.Length > 0)) { imgSrc = treeView.LeafNodeStyle.ImageUrl; } } else if ((treeView.ParentNodeStyle != null) && (treeView.ParentNodeStyle.ImageUrl.Length > 0)) { imgSrc = treeView.ParentNodeStyle.ImageUrl; } } } if ((imgSrc.Length == 0) && (treeView.LevelStyles != null) && (treeView.LevelStyles.Count > item.Depth)) { if (treeView.LevelStyles[item.Depth].ImageUrl.Length > 0) { imgSrc = treeView.LevelStyles[item.Depth].ImageUrl; } } } return imgSrc; } private void AssureAllNodesAreBuilt(TreeView treeView) { if (treeView != null) { int currentDepth = treeView.ExpandDepth; treeView.ExpandDepth = -1; treeView.ExpandAll(); treeView.ExpandDepth = currentDepth; if (treeView.ExpandDepth > -1) { treeView.CollapseAll(); ExpandToDepth(treeView.Nodes, treeView.ExpandDepth); } } } static public void ExpandToDepth(TreeNodeCollection nodes, int expandDepth) { foreach (TreeNode node in nodes) { if (node.Depth < expandDepth) { node.Expand(); ExpandToDepth(node.ChildNodes, expandDepth); } } } } }**************** testTreeView.aspx *********************
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> void DoSelectedNodeChanged(Object sender, EventArgs e) { Message.Text = "You selected: " + TreeView1.SelectedNode.Text; } </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <style> .AspNet-TreeView-Selected { background: yellow; } </style> </head> <body> <form id="form1" runat="server"> <asp:TreeView ID="TreeView1" EnableCssFriendlyAdapter="true" OnSelectedNodeChanged="DoSelectedNodeChanged" runat="server" SkinID="SampleTreeView" CssSelectorClass="PrettyTree"> <Nodes> <asp:TreeNode Text="animals"> <asp:TreeNode Text="elephant" SelectAction="Select" /> <asp:TreeNode Text="lion" SelectAction="Select" /> </asp:TreeNode> <asp:TreeNode Text="fish"> <asp:TreeNode Text="trout" /> <asp:TreeNode Text="tuna" /> </asp:TreeNode> </Nodes> </asp:TreeView> <asp:Label ID="Message" runat="server" /> </form> </body> </html>Groovybits.com
Russ Helfand
Contributor
3304 Points
744 Posts
Re: Experimental TreeView adapter version: with postback and node selection
May 25, 2006 10:53 PM|LINK
Groovybits.com
bttrflii
Member
590 Points
132 Posts
Re: Experimental TreeView adapter version: with postback and node selection
May 26, 2006 03:06 PM|LINK
is there any way you can make a download for us? for example, a zip file of everything we need to test this out, including the folder structure and files so that all we need to do is unzip it to our iis folder? i'll admit that making a new site and having to copy/paste all that is a bit daunting.
[the reason i personally haven't really looked into it (other than the daunting part) is because the features you've added don't really apply to me and were requested by others. the two things i was interested in were keeping the current path expanded and "active" classing the entire path to the current node, but i've gotten those working on my own.]
relish27
Member
150 Points
51 Posts
Re: Experimental TreeView adapter version: with postback and node selection
Jun 22, 2006 02:40 PM|LINK
Russ Helfand
Contributor
3304 Points
744 Posts
Re: Experimental TreeView adapter version: with postback and node selection
Jun 22, 2006 03:15 PM|LINK
OK, maybe I'm confused a bit, too. Ha ha. It seemed like you were asking (in http://forums.asp.net/thread/1321336.aspx) why postback wasn't ending up calling your SelectedNodeChanged event handler. This thread explains that this (and potentially other) postback event handlers are being twarted by design limitations deep in the .Net framework. I'm working with the ASP.NET team to try to work around this so server-side events like SelectedNodeChanged are called upon postback regardless of whether or not adapters are present in the web site.
I think what you and cj did was to modify your version of the adapter so it distinguished the selected state of a node using CSS. That's great and the next rev of the adapters should do the same thing. But whether or not postback event handlers are called on the server is a separate matter.
I don't mean to get on a rant about postbacks and events and such. Can you help me understand better the connection between your question about using an XmlDataSource and your post http://forums.asp.net/thread/1321336.aspx that discusses postback event handler problems.
I'm betting we can fix any problems having to do with using an XmlDataSource rather than a site map data source. But getting the postback events to fire while the adapters are in play may be something we have to defer for the moment.
Groovybits.com
relish27
Member
150 Points
51 Posts
Re: Experimental TreeView adapter version: with postback and node selection
Jun 22, 2006 05:18 PM|LINK
so, to step back... my problem is this - i have three areas of the site with different navigation needs:
i figured i could get #2 to work as #1 is working just by populating the admin treeview with XML instead of the web.sitemap. this would keep these links out of my public sitemap. i've also seen ways to create the XML from a database and/or dynamically, so i figured that would solve #3, but also wouldnt' be using the sitemap datasource.
so, i implemented the admin navigation using XML. because the structure was slightly different than the main navigation, i adjusted the CSS for this area and it displays and rolls over fine. however, if you click on a nav item (which has a URL, so the page does refresh), that nav item doesn't show the selected state as is does on my #1 nav. that is, when i look at the source code i can see that the CSS style is the same as all the others.
going back to the adapter cs, that makes me wonder why it's not triggering the item.Selected == true conditionals or any of cj's isActivePath conditionals. that's why i was wondering if there was anything about using the sitemap datasource made the adapter function differently. it doesn't seem that it should, so i'm hoping that i'm just overlooking something here. it would really solve a lot of my problems here (i think) if i could get this to work in the same fashion.
i'll keep plugging away at it, but if you have any thoughts, i do appreciate them!
c
Russ Helfand
Contributor
3304 Points
744 Posts
Re: Experimental TreeView adapter version: with postback and node selection
Jun 22, 2006 05:46 PM|LINK
Look at the original version of the kit's web.config and the TreeView sample aspx. You'll see that the web.config sets up multiple site maps. What you do is to add entries in your web.config that point to different files that use the sitemap format. Then you refer to those sitemap providers specifically in your SiteMapDataSource. So you can always simply pair your TreeView with a SiteMapDataSource if you like. The same is true for Menus, etc. You don't have to roll your own XML if you don't want to.
That said, if you did roll your own XML for the TreeView so you could bind it to an XmlDataSource it still ought to work because the TreeView (and its adapter) doesn't know or or care about where its data comes from. At least, that's the intent.
If this isn't working for you, with XmlDataSources, I need you to post some of your code so I can look more closely at what you are doing.
Groovybits.com
relish27
Member
150 Points
51 Posts
Re: Experimental TreeView adapter version: with postback and node selection
Jun 22, 2006 07:27 PM|LINK
i still don't know why the XML wasn't working correctly, but will have to hold off on that for now. i'll see how the blog nav works and post back about how that goes, for better or worse. :)
dan13l
Member
5 Points
1 Post
Re: Experimental TreeView adapter version: with postback and node selection
Jun 28, 2006 03:42 PM|LINK
Having encountered a performance problem with IE and a nested version of the out of the box Treeview control (my masterpage has a few tables and as a result, a 181 node treeview takes roughly 5 seconds to render) I started playing with the CSS friendly version.
The CSS friendly version fixes my problem, and before finding your solution for postbacks and selected node, I managed to reverse engineer the same thing (thank God for Reflector!).
My problem is that the tree doesn't remember its state between postbacks. I can't seem to hack this into working, and haven't found a way to make it work yet.
I'm going to keep trying, but any thoughts you have in the meantime would be appreciated.
Thanks,
Dan.
Russ Helfand
Contributor
3304 Points
744 Posts
Re: Experimental TreeView adapter version: with postback and node selection
Jun 28, 2006 07:54 PM|LINK
Hi Dan, I'd like to try to help. I've been working a lot on the TreeView adapter since I posted the version shown above. It still encompasses much of what you see above but now includes a few other things (and some of the code shown above has been cleaned up, refactored, renamed, etc.). I don't want post all of those changes/updates yet so I'm going to try to give you instructions for how you can do some surgical enhancements to the code shown above to begin to achieve a rudimentary but (in my opinion) effective re-expansion functionality with your TreeView.
My premise is simple: in many cases the end user is only interested in having the tree re-expand to show their selected node. They don't really care to see the expansion of other parts of the tree that they may have been exploring before selecting a node. In these cases, you can achieve that behavior with a simple modification to the adapter (shown below). That said, I do realize that this re-expansion methodology isn't going to satisfy everyone. But I need to take things one step at a time layering in better and better functionality.
So, here is what I would suggest you do to enhance your TreeView adapter for now...
Start with the adapter code shown above. Find the call to AssureAllNodesAreBuilt in RenderContents. Immediately after that call, add another method call to a new method you'll write called ExpandToSelectedNode(). Here is it's code:
private void ExpandToSelectedNode()
{
TreeView treeView = Control as TreeView;
if ((treeView != null) && (treeView.SelectedNode != null))
{
treeView.CollapseAll();
TreeNode nodeToExpand = treeView.SelectedNode.Parent;
while (nodeToExpand != null)
{
nodeToExpand.Expanded = true;
nodeToExpand = nodeToExpand.Parent;
}
}
}
Would you give that a shot and let me know what you think?
Groovybits.com