(Imperfect) Solution to TreeView Postback / Client-Side Node Selection Issue

I've seen this question posted on all corners of the web... "How do I disable "AutoPostBack" on the ASP.NET 2.0 TreeView control?!"  Unfortunately, most of the answers either don't work, miss the point (don't work right), or boil down to "You can't do it."  I happen to know that this behavior worked perfectly in the IEWebControls TreeView that Microsoft released as an add-on prior to ASP.NET 2.0, however.  So I set out to find a solution for the ASP.NET 2.0 TreeView issue.

In a nutshell, the behavior that I and others are looking for is to have a TreeView rendered in a page that allows the user to expand, contract, and select nodes within the TreeView without causing a PostBack to the server.  This implies two things: (1) the most recently-selected node should be recorded as the currently-selected node [i.e., at PostBack time, the most-recently selected node is actually represented as the SelectedNode]; and (2) the selected node should exhibit the SelectedNodeStyle as specified in the TreeView declaration.

It appears that the TreeView engineers saw only two possible outcomes from selecting a leaf node in a tree: (1) immediately posting back to the server, or (2) immediately navigating to another web page.  They apparently did not consider option (3) just allowing selection in-place on the client, while waiting for a click on some other control in the form to post the form back to the server.

So I dug into the client-side code for the TreeView control, which consists of not only the rendered TreeView content, but a set of CSS classes, a library of JavaScript functions, and a block of JavaScript that establishes the TreeView's "Data" structure.  I was joined in this effort by www.asp.net forum user Pushpendra (pushp_aspnet), who contributed significantly to this solution.  The crazy bit is that, in the end, most of the groundwork to allow this functionality already exists, albeit in somewhat buggy form.

So without further ado, here is the crux of the solution:

1. In order to prevent PostBack, each TreeNode's NavigateUrl (which translates to the A tag's HREF attribute) must be set to "javascript:void(0);".  This stops the form post process before it begins.

2. In order to take advantage of existing client-side expand/collapse functionality, each TreeNode's SelectAction must be set to TreeNodeSelectAction.SelectExpand.

3. In order for the SelectedNodeStyle to ever be applied in client script, the TreeView's Target attribute must be set to "_self".

4. If any HoverNodeStyle is applied to the TreeView, the SelectedNodeStyle must be *manually* added to the TreeView's "_Data" structure (which keeps track of the TreeView's state during its lifetime on the client).  I have no idea why, but if any HoverNodeStyle is specified for the TreeView, the SelectedNodeStyle is not introduced to the TreeView's _Data structure, and client-side node selection (using the built-in JavaScript library function) will *always fail*.

5. Two of the TreeView's JavaScript library functions must be overridden to overcome bugs (shortcomings? functionality that was never meant to exist?).  TreeView_SelectNode does not always properly remove the Hover style from nodes as they're de-selected, and TreeView_UnhoverNode improperly removes the SelectedNodeStyle from the selected node on mouse-out.  Overriding of these two functions is possible because (at least in IE6, the only platform I currently have at my disposal) if more than one JavaScript function exists with the same name, the one that appears last in the page "wins."  So the challenge is making sure that the rewritten JavaScript functions appear later in the page than the internal TreeView JavaScript library versions.

After all of these are done, you will have a TreeView that allows proper node selection on the client.  The one shortcoming is that once in a while a deselected node will retain the "HoverNodeStyle".  I can't figure out why this is, and am not thrilled with debugging the JavaScript.  It's a minor, intermittent, cosmetic bug, so I'm happy enough with it for now.  If anyone reading this figures it out, please return the favor by posting the fix to this forum!

To address all of these issues in the neatest way I know how, I've created the following two C# methods, which I stuffed in a "TreeViewHelper" static class library, and I call late in my page's "Page_Load" handler.  Without further ado, here are the two methods (one public, one private [called by the first, and recurses on itself]):

/// <summary>
/// Fixes the ASP.NET 2.0 TreeView's inability to select a node (and have the style
/// properly applied at the client) without PostBack.
/// </summary>
/// <param name="tv">The TreeView object that is being fixed</param>
/// <param name="SelectedClassStyleID">The ID emitted by ASP.NET for the TreeView's SelectedClass (e.g., \"TreeView1_3\"). View Source for the page with the TreeView control and look at the top for the classes emitted in the style block.</param>
/// <param name="SelectedHyperLinkStyleID">The ID emitted by ASP.NET for the TreeView's SelectedHyperLinkClass (leave blank if none). View Source for the page with the TreeView control and look at the top for the classes emitted in the style block.</param>

public static void ClientSelectFix(PlaceHolder plh, TreeView tv, string SelectedClassStyleID, string SelectedHyperLinkStyleID)
{
   // Make a couple of modifications to the TreeView in preparation
   tv.Target = "_self";
   DisableAutoPostBack(tv.Nodes);

   // Now build work-around for the ASP.NET 2.0 TreeView's JavaScript library
   string TreeViewID = tv.ClientID;

   // The SelectedClassStyleID and SelectedHyperLinkStyleID may change depending on the styles
   // supplied for the TreeView, and may change as styles are modified. Look at the <style>
   // block at the top of the generated HTML page to determine the names given to these classes.
   // Leave blank to emit a blank classname.

   string SelectedClass = string.Empty;
   if (SelectedClassStyleID != string.Empty)
      SelectedClass = TreeViewID +
"_" + SelectedClassStyleID;

   string SelectedHyperLinkClass = string.Empty;
   if (SelectedHyperLinkStyleID != string.Empty)
      SelectedHyperLinkClass = TreeViewID +
"_" + SelectedHyperLinkStyleID;

   string TreeViewClientSelectFix; // The string within which to build the JavaScript fix
   TreeViewClientSelectFix = @"
<script>
// These two elements are not emitted into the "
+ TreeViewID + @"_Data
// structure if a HoverNodeStyle exists, preventing client-side node
// selection from working.
"
+ TreeViewID + @"_Data.selectedClass = '" + SelectedClass + @"';
"
+ TreeViewID + @"_Data.selectedHyperLinkClass = '" + SelectedHyperLinkClass + @"';

// This is a duplicate of the Microsoft TreeView JavaScript library
// function, but appears later in the page and overrides the library
// version. This one does not Unhover a node if it has the 'selected'
// class applied to it.
function TreeView_UnhoverNode(node)
{
   if (node.className.indexOf('"
+ SelectedClass + @"') == -1)
   {
      WebForm_RemoveClassName(node, node.hoverClass);
      if (__nonMSDOMBrowser)
      {
         node = node.childNodes[node.childNodes.length - 1];
      }
      else
      {
         node = node.children[node.children.length - 1];
      }
      WebForm_RemoveClassName(node, node.hoverHyperLinkClass);
   }
}

// This is a duplicate of the Microsoft TreeView JavaScript library
// function, but appears later in the page and overrides the library
// version. This one takes care to remove the hoverClass from the
// de-selected node.  Contributed by Pushpendra.
function TreeView_SelectNode(data, node, nodeId)
{
   if ((typeof(data.selectedClass) != 'undefined') && (data.selectedClass != null))
   {
      var id = data.selectedNodeID.value;
      if (id.length > 0)
      {
         var selectedNode = document.getElementById(id);
         if ((typeof(selectedNode) != 'undefined') && (selectedNode != null))
         {
            WebForm_RemoveClassName(selectedNode, data.selectedHyperLinkClass);
            selectedNode = WebForm_GetParentByTagName(selectedNode, 'TD');
            WebForm_RemoveClassName(selectedNode, data.selectedClass);

            //removing the extra class from the node's parent Element
            WebForm_RemoveClassName(selectedNode, data.hoverClass);
         }
      }
      WebForm_AppendToClassName(node, data.selectedHyperLinkClass);
      node = WebForm_GetParentByTagName(node, 'TD');
      WebForm_AppendToClassName(node, data.selectedClass)
   }
   data.selectedNodeID.value = nodeId;
}
</script>"

;

   plh.Controls.Clear();
   plh.Controls.Add(

new LiteralControl(TreeViewClientSelectFix));
}

public static void DisableAutoPostBack(TreeNodeCollection tnc)
{
   // Loop over every node in the passed collection
   foreach (TreeNode tn in tnc)
   {
      // Set the node's NavigateUrl (which equates to A HREF) to javascript:void(0);,
      // effectively intercepting the click event and disabling PostBack.
      tn.NavigateUrl = "javascript:void(0);";

      // Set the node's SelectAction to SelectExpand to enable client-side
      // expansion/collapsing of parent nodes
      tn.SelectAction = TreeNodeSelectAction.SelectExpand;

      // If this node has children, recurse over them as well before returning
      if (tn.ChildNodes.Count > 0)
      {
         DisableAutoPostBack(tn.ChildNodes);
      }
   }
}

 

Here are definitions of the 4 parameters the ClientSelectFix method requires:

PlaceHolder plh
Because the JavaScript functions emitted by this function *must* appear later in the page than the functions emitted by ASP.NET to accompany the TreeView, and because the Page.ClientScript.RegisterScriptBlock method does *not* guarantee the order in which scripts are emitted (and, in fact, emits added libraries earlier in the page than the _Data JavaScript structure emitted by the TreeView), I had to take more drastic measures, and leave a PlaceHolder just outside (below) the closing </form> tag on the page, and emit the JavaScript fix to that PlaceHolder.  The page on which the TreeView you need fixed exists, place a PlaceHolder control after the </form> tag, and pass the PlaceHolder as the first parameter tot his method.

TreeView tv
This is simply the TreeView object that needs to be fixed.

SelectedClassStyleID
If you observe the emitted HTML page on which your TreeView exists, at the top is a <style> block that contains emitted styles to represent the different styles applied to your TreeView.  For example, if your TreeView's ID is "tvData", you may see classes named "tvData_0", "tvData_1", and so on.  These classes correlate to the styles applied to the TreeView control.  You will need to look at the emitted JavaScript to determine which of the emitted <style> classes corresponds to your SelectedNodeStyle.  In fact, depending which DHTML attributes you've modified with the style, there may be two classes emitted -- one for the style of the A element's text, and one for its surrounding TD element.  If tvData_3 represents the TD element, then you want to pass "3" as the SelectedClassStyleID.

SelectedHyperLinkStyleID
As mentioned above, a SelectedNodeStyle may correspond to more than one CSS class.  If there is a separate class representing the A element, pass its ID in this parameter.  For example, if "tvData_4" represents the A element, then pass "4" as the SelectedHyperLinkStyleID.

 

Here is a representative page that properly uses the ClientSelectFix:

<%

@ Page Language="C#" AutoEventWireup="true" CodeBehind="TestTreeView.aspx.cs" Inherits="TestTreeView.TestTreeView" %>

<!

DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<

html xmlns="http://www.w3.org/1999/xhtml" >
   <head runat="server">
      <title>TreeView Experiment</title>
   </head>
   <body>
      <form id="form1" runat="server">
         <asp:TreeView ID="tvData" Runat="server" Target="_self">
            <NodeStyle Font-Names="Vardana, Geneva, Arial, Helvetica, sans-serif" Font-Size="10px"
               ForeColor="darkblue" BorderColor="white" BorderWidth="1" BorderStyle="solid"
               HorizontalPadding="2" VerticalPadding="2" />
            <SelectedNodeStyle BorderStyle="solid" BorderWidth="1" BorderColor="DarkBlue" BackColor="#dddddd" />
            <HoverNodeStyle BorderStyle="solid" BorderWidth="1" BorderColor="darkblue" />
            <Nodes>
               <asp:TreeNode Text="Node 1"/>
               <asp:TreeNode Text="Node 2">
                  <asp:TreeNode Text="Node 2.1" />
                  <asp:TreeNode Text="Node 2.2" />
               </asp:TreeNode>
            </Nodes>
         </asp:TreeView>
      </form>
      <asp:PlaceHolder ID="plhTreeViewClientSelectFix" runat="server" />
   </body>
</
html>

 

... and in its CodeBehind file:

 

public partial class TestTreeView : System.Web.UI.Page
{
   protected void Page_Load(object sender, EventArgs e)
   {
      TreeViewHelper.ClientSelectFix(plhTreeViewClientSelectFix, tvData, "3", string.Empty);  // in my example, tvData_3 is the SelectedNodeStyle
   }
}

 

Enjoy!

-Bryan

 

0
bryanowen
11/3/2006 6:44:38 PM
asp.net.presentation-controls 72751 articles. 3 followers. Follow

13 Replies
2923 Views

Similar Articles

[PageSpeed] 55

I figured out the "intermittent" hover style artifact issue.  It happened whenever a node was selected, and I moused out of the selected node, then back into it, then back out, and then selected another node.  The hoverClass was being applied twice to the node.  The Unhover routine was only removing one reference to the class.  I think this may be because the TreeView engineers didn't design the TreeView to be statically selected on the client, so didn't need to worry about this type of scenario.  (?)  Anyway, I have added one more modification to the "fix" for this issue, which clears up the remnants of the hover style.  Unfortunately I've noticed another issue, which may or may not be related to this fix.  Now whenever I expand a node by clicking on the node's text (versus clicking on the expand/contract [+ / -] icon), the icon disappears.  (Hrmph.)  Anybody clever enough to figure this one out?  In the meantime, modifying the DisableAutoPostBack routing below to set each node's SelectAction to TreeNodeSelectAction.Select (instead of SelectExpand) skirts the problem -- but you don't get the SelectExpand feature.  I've changed it in the routine below.  Some clever JavaScript guru will need to figure out why the image is disappearing in order for SelectExpand to work with this fix, but that seems like a pretty minor trade-off in the big scheme.  (To me, anyway.)

Here's the modified and less-imperfect Client-side (non-PostBack) TreeView Select fix:

/// <summary>
/// Fixes the ASP.NET 2.0 TreeView's inability to select a node (and have the style
/// properly applied at the client) without PostBack.
/// </summary>
/// <param name="tv">The TreeView object that is being fixed</param>
/// <param name="SelectedClassStyleID">The ID emitted by ASP.NET for the TreeView's SelectedClass (e.g., \"TreeView1_3\"). View Source for the page with the TreeView control and look at the top for the classes emitted in the style block.</param>
/// <param name="SelectedHyperLinkStyleID">The ID emitted by ASP.NET for the TreeView's SelectedHyperLinkClass (leave blank if none). View Source for the page with the TreeView control and look at the top for the classes emitted in the style block.</param>

 

public static void ClientSelectFix(PlaceHolder plh, TreeView tv, string SelectedClassStyleID, string SelectedHyperLinkStyleID)
{
   // Make a couple of modifications to the TreeView in preparation
   tv.Target = "_self";
   DisableAutoPostBack(tv.Nodes);

 

   // Now build work-around for the ASP.NET 2.0 TreeView's JavaScript library
   string TreeViewID = tv.ClientID;

 

   // The SelectedClassStyleID and SelectedHyperLinkStyleID may change depending on the styles
   // supplied for the TreeView, and may change as styles are modified. Look at the <style>
   // block at the top of the generated HTML page to determine the names given to these classes.
   // Leave blank to emit a blank classname.

 

   string SelectedClass = string.Empty;
   if (SelectedClassStyleID != string.Empty)
      SelectedClass = TreeViewID +
"_" + SelectedClassStyleID;

 

   string SelectedHyperLinkClass = string.Empty;
   if (SelectedHyperLinkStyleID != string.Empty)
      SelectedHyperLinkClass = TreeViewID +
"_" + SelectedHyperLinkStyleID;

 

   string TreeViewClientSelectFix; // The string within which to build the JavaScript fix
   TreeViewClientSelectFix = @"
<script>
   // These two elements are not emitted into the "
+ TreeViewID + @"_Data
   // structure if a HoverNodeStyle exists, preventing client-side node
   // selection from working.
   "
+ TreeViewID + @"_Data.selectedClass = '" + SelectedClass + @"';
   "
+ TreeViewID + @"_Data.selectedHyperLinkClass = '" + SelectedHyperLinkClass + @"';

   // These are duplicates of the Microsoft TreeView JavaScript library
   // functions, but appear later in the page and override the library
   // versions.

   // This function is modified so that it does not Unhover a node if it has the 'selected' class applied to it.
   function TreeView_UnhoverNode(node)
   {
      if (node.className.indexOf('"
+ SelectedClass + @"') == -1) // This check is added to the original function
      {
         WebForm_RemoveClassName(node, node.hoverClass);
         if (__nonMSDOMBrowser)
         {
            node = node.childNodes[node.childNodes.length - 1];
         }
         else
         {
            node = node.children[node.children.length - 1];
         }
         WebForm_RemoveClassName(node, node.hoverHyperLinkClass);
      }
   }

   // This function is modified to remove the hoverClass from the de-selected node
   function TreeView_SelectNode(data, node, nodeId)
   {
      if ((typeof(data.selectedClass) != 'undefined') && (data.selectedClass != null))
      {
         var id = data.selectedNodeID.value;
         if (id.length > 0)
         {
            var selectedNode = document.getElementById(id);
            if ((typeof(selectedNode) != 'undefined') && (selectedNode != null))
            {
               WebForm_RemoveClassName(selectedNode, data.selectedHyperLinkClass);
               selectedNode = WebForm_GetParentByTagName(selectedNode, 'TD');
               WebForm_RemoveClassName(selectedNode, data.selectedClass);

               WebForm_RemoveClassName(selectedNode, data.hoverClass); // This call is added to the original function
            }
         }
         WebForm_AppendToClassName(node, data.selectedHyperLinkClass);
         node = WebForm_GetParentByTagName(node, 'TD');
         WebForm_AppendToClassName(node, data.selectedClass)
      }
      data.selectedNodeID.value = nodeId;
   }

   // This function is modified so it doesn't re-add a class if it's already applied
   function WebForm_AppendToClassName(element, className)
   {
      var current = element.className;
      if (current)
      {
         if (current.indexOf(className) == -1) // This check is added to the original function
         {
            if (current.charAt(current.length - 1) != ' ')
            {
               current += ' ';
            }
            current += className;
         }
      }
      else
      {
         current = className;
      }
      element.className = current;
   }
</script>";

   plh.Controls.Clear();
   plh.Controls.Add(
new LiteralControl(TreeViewClientSelectFix));
}

 

public static void DisableAutoPostBack(TreeNodeCollection tnc)
{
   // Loop over every node in the passed collection
   foreach (TreeNode tn in tnc)
   {
      // Set the node's NavigateUrl (which equates to A HREF) to javascript:void(0);,
      // effectively intercepting the click event and disabling PostBack.
      tn.NavigateUrl = "javascript:void(0);";

      // Set the node's SelectAction to Select in order to enable client-side
      // expansion/collapsing of parent nodes.  Caution: SelectExpand causes
      // expand/collapse icon to disappear!

      tn.SelectAction = TreeNodeSelectAction.Select;

      // If this node has children, recurse over them as well before returning
      if (tn.ChildNodes.Count > 0)
      {
         DisableAutoPostBack(tn.ChildNodes);
      }
   }
}

 

0
bryanowen
11/6/2006 4:14:41 PM

Hello Bryan,

First of all, thank you for posting this Treeview selection without PostBack article. I'm now using it in my own solution.

I had a bit of a struggle with the various stylesheets applied to the treenodes, like you had.
I found out there is a bug in the stock Javascript function WebForm_RemoveClassName. I suspect this could also account for the odd things you've encountered with hover styles etc.

For me the javascript part I now actually have overriden is only this function WebForm_RemoveClassName. All hovering and unhovering, selecting etc. now behaves as I expect it to behave. I still had to include the selectedClass in the Data structure. So perhaps you also would like to test and see if bugfixing only this function is all you need.

Searching for the bug on the web, I found a posting on this forum that mentions there are actually two bugs in this function: http://forums.asp.net/thread/1578977.aspx (posting by joshin). I only encountered the second bug and fixed it like in another posting on http://www.thescripts.com/forum/thread557649.html (by Cosmin), but I think I'll adjust it to the fix of joshin.

Second, in my solution I wanted to use a CssClass instead of the other attributes for style. This needs for an adjustment in ClientSelectFix, because the CssClass names are added before the generated StyleIDs.

Third, I don't use the Placeholder to insert the Javascript, but I'm using RegisterStartupScript. This adds the javascript always inside the last piece of javascript that ASP.NET adds to the page so you know it's always included after the stock functions like needed. So I'm passing the ClientScriptManager to the function ClientSelectFix instead of the placeholder to be able to call RegisterStartupScript.

 

interface fix:

public static void ClientSelectFix(ClientScriptManager csm, TreeView tv, string SelectedClassStyleID, string SelectedHyperLinkStyleID, string SelectedClassStyleName, string selectedHyperLinkStyleName)

inside:

      string SelectedClass = string.Empty;
      if (SelectedClassStyleID != string.Empty)
        SelectedClass = TreeViewID + "_" + SelectedClassStyleID;

      if (SelectedClassStyleName != string.Empty)
        SelectedClass = SelectedClassStyleName + " " + SelectedClass;


      string SelectedHyperLinkClass = string.Empty;
      if (SelectedHyperLinkStyleID != string.Empty)
        SelectedHyperLinkClass = TreeViewID + "_" + SelectedHyperLinkStyleID;

      if (selectedHyperLinkStyleName != string.Empty)
        SelectedHyperLinkClass = selectedHyperLinkStyleName + " " + SelectedHyperLinkClass;

and as said I only included javascript function WebForm_RemoveClassName (and no longer the other functions).

And finally to inject WebForm_RemoveClassName and the Data.selectedClass I do this in the end:

      Page page = HttpContext.Current.Handler as Page;
      if (page != null)
        csm.RegisterStartupScript(page.GetType(), "TreeViewClientSelectFix", TreeViewClientSelectFix);

instead of adding it to the placeholder. 

I hope this maybe will help you and/or others.

Erik Jan

0
Eegee0
4/11/2007 7:48:32 PM

Erik,

Thank you so much for adding this to the solution!  I'm not a JavaScript guru, so I missed the bit about the RemoveClassName not working properly.  And I absolutely *love* the RegisterStartupScript technique, which doesn't require a placeholder in the page.  I know this whole fix is hackety-hackville, but just removing the necessity for a placeholder makes it a much more respectable one, and I appreciate that!

Thanks for your contribution!

Has anybody looked to see if this bug still exists in Orcas?

-Bryan

 

0
bryanowen
4/24/2007 4:47:14 PM

 hi,

First of all I would like to thank the people who spend their valuable time for developing this piece of code to over come this matter, before finding this piece of code I was wondering what do I need to do to over come the problem of "javascript: _doPostBack() " and after integrating the following code to my project I managed to overcome it. 

But I do have another small problem that is when I click on the node of the list view in the first time it refreshes the whole page. Pls show me a way to over come this.Sad Thank you.

hayesha. 

0
hayesha
5/30/2007 3:31:06 PM

Hayesha,

The "DisableAutoPostBack" recursive function in the library I posted should start at the top of the TreeView and disable postback (by setting the action for each node to javascript:void(0);) on every single node in the TreeView.  This method is called by the second line of code of the ClientSelectFix method.  Two things come to mind... (1) are you properly passing the TreeView control into the ClientSelectFix method? and (2) somewhere after the call to ClientSelectFix, are you setting the NavigateUrl or SelectAction of any of the nodes in your TreeView (i.e., overriding the values set by the fix)?

If you can post your code -- the .aspx page and the .aspx.cs (or .aspx.vb) (if you use code-behind), that would make the problem a lot easier to troubeshoot.

Thanks!

-Bryan

 

0
bryanowen
5/30/2007 6:29:22 PM

 Bryan,

Thank you very much for responding to the matter very quickly, the code is pretty long,

I'll try with what you  have directed with.

Thank you.

Hayesha. 

 

 

 

 

 

Hayesha. 

 

 

0
hayesha
5/31/2007 11:55:36 AM
I've encountered with the same problem.
But I don't understand what are you using Css styles for?
Standart function TreeView_SelectNode makes all you want: mark the node as selected.
The problem is : how to call the function on client node click? how to put call of the TreeView_SelectNode into onclick attribute of every html element representing node?

Unfortunatly, if you set NavigateUrl property of treenode to any non-empty value, than clicking on the node won't raise enithing! (except redirecting to NavigateUrl target)
Not empty NavigateUrl property entails that onclick will be empty for every html element TreeNode was rendered in.
0
crazypotato
7/13/2007 4:25:55 PM

crazypotato:
I've encountered with the same problem. But I don't understand what are you using Css styles for? Standart function TreeView_SelectNode makes all you want: mark the node as selected.

The TreeView_SelectNode function indirectly adds a CSS "class" to the selected node.  That class in itself doesn't do anything to the style of the node text; only through the CSS associated with that class is a change made to the appearance of the node.  I suppose you could rewrite the SelectNode function so that it directly, for example, sets the foreground and background color of the selected node's text, but in this case we just add a class to the node, and let CSS take care of the rest.  I think this is a preferable solution, and it happens to be the way that the designers of the TreeView control did it.

crazypotato:
The problem is : how to call the function on client node click? how to put call of the TreeView_SelectNode into onclick attribute of every html element representing node? Unfortunatly, if you set NavigateUrl property of treenode to any non-empty value, than clicking on the node won't raise enithing! (except redirecting to NavigateUrl target) Not empty NavigateUrl property entails that onclick will be empty for every html element TreeNode was rendered in.

I don't know how to solve this problem off the top of my head, and I've temporarily moved on from the project that required me to do the work I posted earlier in this thread, but I have a couple of thoughts on it:

1. I believe the NavigateUrl value ends up in the node's "href" and not its "onclick" attribute.

2. You might be able to loop through the nodes in the TreeView's nodes and do a .Attributes.Add("onClick", "/* whatever Javascript action you want here*/");  That way the "href" stays "javascript:void(0);", and the onClick calls the actual function that does whatever you want to do in-page.

I wish I had the time right now to fire up the project and take a look, and possibly give you a more substantial answer, but unfortunately I don't.

-Bryan

 

0
bryanowen
7/13/2007 5:53:44 PM

Here's another way that I've found. It appears as though, when the page first loads, the TreeView want's to be on-screen. I've placed mine in a div, with style.display = 'block'. On the initial page, the tree is visible in a MultiView panel. After my users click "next", I switch panels, setting style.display = 'none', hiding it untill needed.

My tree view only shows errors associated with the user's interaction with my site. Once they throw an error, even after several postbacks, I flip views on the multi view and the errors show up just fine (the tree view renders it's HoverNodeStyle like it's supposed to.)

0
TravisMay6
11/5/2007 3:47:44 PM

there is actually a much simpler solution...

 node.SelectAction = TreeNodeSelectAction.None

0
mathisjay
12/31/2007 4:45:01 PM

 mathisjay, but in this case you lose the ability to choose elements of TreeView.

0
Idsa
5/6/2008 8:58:45 PM

Here is my solution with far less code,  at least its working for the way I use it.  My goal was a single select TreeView that does not post on clicking Nodes as I have a separate submit button to post the page.  Each node must deselect the previous node that was clicked

I populated the TreeView nodes on the server from the database.  My TreeView is called treeGeo

1) Populated Nodes,  increment the Count variable.  This will match the id of the anchor tag it generates ie 'treeGeot0,  'treeGeot1 ect.  My treeView is 3 levels deep so it works out in my case that the Count variable is going to be the same as whats generated in view source on your aspx page for the unique number for each anchor tag.

TreeNode nodeCompanywide = new TreeNode();

nodeCompanywide.Text = Constants.Companywide;

nodeCompanywide.Value = Constants.Companywide + "," + Constants.Companywide;

nodeCompanywide.NavigateUrl = "javascript:treeClicked('treeGeot" + Count++ + "')";

// nodeCompanywide.Selected = true;

treeGeo.Nodes.Add(nodeCompanywide);

2) Add this javascript method to you page

function treeClicked(nodeID){

 

var id = document.getElementById("hdnPrevNode").value;

if((id != nodeID) && (id!=""))

{document.getElementById(id).parentNode.className = "treeGeo_0";  //Set the style of the partent TD tag so it shows its not selected

 

}

 

document.getElementById(
"hdnPrevNode").value = nodeID;

}

3) Add a hidden tag to keep track or previously selected Node ids between posts or treeView clicks

<asp:HiddenField ID="hdnPrevNode" runat="server" Value=""/>

 4)  Add this to you treeView tag

Target="_self"

 

 

 

0
g08h
5/14/2008 9:46:04 PM
bryanowen:

crazypotato:
I've encountered with the same problem. But I don't understand what are you using Css styles for? Standart function TreeView_SelectNode makes all you want: mark the node as selected.

The TreeView_SelectNode function indirectly adds a CSS "class" to the selected node.  That class in itself doesn't do anything to the style of the node text; only through the CSS associated with that class is a change made to the appearance of the node.  I suppose you could rewrite the SelectNode function so that it directly, for example, sets the foreground and background color of the selected node's text, but in this case we just add a class to the node, and let CSS take care of the rest.  I think this is a preferable solution, and it happens to be the way that the designers of the TreeView control did it.

crazypotato:
The problem is : how to call the function on client node click? how to put call of the TreeView_SelectNode into onclick attribute of every html element representing node? Unfortunatly, if you set NavigateUrl property of treenode to any non-empty value, than clicking on the node won't raise enithing! (except redirecting to NavigateUrl target) Not empty NavigateUrl property entails that onclick will be empty for every html element TreeNode was rendered in.

I don't know how to solve this problem off the top of my head, and I've temporarily moved on from the project that required me to do the work I posted earlier in this thread, but I have a couple of thoughts on it:

1. I believe the NavigateUrl value ends up in the node's "href" and not its "onclick" attribute.

2. You might be able to loop through the nodes in the TreeView's nodes and do a .Attributes.Add("onClick", "/* whatever Javascript action you want here*/");  That way the "href" stays "javascript:void(0);", and the onClick calls the actual function that does whatever you want to do in-page.

I wish I had the time right now to fire up the project and take a look, and possibly give you a more substantial answer, but unfortunately I don't.

-Bryan

 

for number 2 question

TreeNode tn = new TreeNode("text","value");

tn.NavigateUrl = "javascript:testing('text', 'value');";

so when u click the node it will run javascript function testing() and you know which node u click base on it's value, u can define the testing() function in your aspx, it will still without postback.

In my case what i want to do is similar to that, so i have 2 treeview, if i click the 1st one i want to populate the 2nd one without postback, i haven't found way to do it without postback :(, i'm using AjaxPro the problem is when function testing() call the function in .cs it didn't recognize the 2nd treeview object still can't figure out why.

0
silenr0c
8/11/2008 2:37:37 AM
Reply: