Showing posts with label treenode. Show all posts
Showing posts with label treenode. Show all posts

Wednesday, March 28, 2012

Treeview and HoverMenuExtender

Is there any way to use the HoverMenuExtender with the Treeview? I tried overriding RenderPostText of the treenode and stuffing the extender in, but there's no control collection to stuff it into.

Thanks!

Hi bjpierron,

Unfortunately, I think the answer is no. I was able to get a very, very hacky version to run, but I don't think you'd be able to use it for any real scenarios. I don't think thatTreeView, and specificallyTreeNode, are extensible enough for you to add this support on top. With some really creative CSS you might be able to get the effect you're looking for using theHoverNodeStyle, but that's bout all I can suggest.

If you were interested, here's how I kind of got it not quite working... I created my ownHoverMenuTreeNode class that inherited offTreeNode. I added aPopupControlID property and variable toHoverMenuTreeNode to store the ID of the control to hover. In itsRenderPreText method I then 1) got a reference to the current page viaHttpContext.Current.CurrentHandler as Page, 2) checked the page's controls recursively to make sure a HoverMenuExtender was included (this ensures the necessary script is downloaded to the client) or I throw an exception that you need aHoverMenuExtender on the page when usingHoverMenuTreeNode, 3) got a reference to thepopupControl usingPage.FindControl and thePopupControlID variable, 4) used theHtmlTextWriter to write the start of adiv tag including a random id (I just used a GUID), 5) created a script that when executed did the exact same things as the JavaScript inthis post after a 1000 ms timeout (using the randomly generated ID and thepopupControl.ClientID), and 6) registered the script as a startup script with the page. Then in theRenderPostText I wrote out the end tag of thediv. What we're essentially doing is wrapping theTreeNodein adiv and dynamically hooking up theHoverMenuBehavior to it. This whole thing looks a lot messier than just adding controls to the page, but I couldn't find a way to do that usingTreeNode (as it's not aControl). The reason that this will never work reliably in practice is that we can't run our code to wireup the behavior until the "Atlas" scripts and our HoverMenuBehavior.js have run. This is why I added the timeout on the script to prevent it from running for a second to see if I could get it working... but it's not a safe thing to do in practice. Here's the code:

// WARNING: THIS IS VERY BAD. IT IS PRESENTED FOR LEARNING PURPOSES ONLY.// PLEASE DO NOT USE THIS CODE IN ANY APPLICATION YOU WRITEusing System;using System.Collections.Generic;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.HtmlControls;using AtlasControlToolkit;namespace ToolkitDemo{/// <summary> /// The HoverMenuTreeNode provides HoverMenu support on top of a standard /// TreeNode. You must have a TreeNode extender on your page for this to work. /// </summary>public class HoverMenuTreeNode : TreeNode {/// <summary> /// ID of the control that will display when this node is hovered /// </summary>private string _popupControlID =null;/// <summary> /// ID of the control that will display when this node is hovered /// </summary> [IDReferenceProperty(typeof(Control))]public string PopupControlID {get {return _popupControlID; }set { _popupControlID =value; } }/// <summary> /// Wrap the TreeNode in a div and write a startup script to wireup /// a HoverMenuBehavior to that div to display our the PopupControl /// </summary> /// <param name="writer">Html Writer</param>protected override void RenderPreText(HtmlTextWriter writer) {// Get a reference to the current page Page page = HttpContext.Current.CurrentHandleras Page;if (page ==null)throw new NotSupportedException("HoverMenuTreeNode can only be used in System.Web.UI.Page");// Recursively check to ensure the page contains a hovermenucontrolbool foundExtender =false; Queue controls =new Queue(); controls.Enqueue(page);while (controls.Count > 0) { Control current = controls.Dequeue(); foundExtender = currentis HoverMenuExtender;if (foundExtender)break;foreach (Control ctrlin current.Controls) controls.Enqueue(ctrl); } controls.Clear();if (!foundExtender)throw new NotSupportedException("HoverMenuTreeNode requires a HoverMenuExtender present on the Page");// Get a reference to the PopupControl Control popupControl = page.FindControl(_popupControlID);if (popupControl ==null)throw new NotSupportedException("HoverMenuTreeNode could not find a control with id \"" + _popupControlID + "\"");// Write out the start of the div that wraps the TreeNodestring id = Guid.NewGuid().ToString(); writer.WriteBeginTag("div"); writer.WriteAttribute("id", id); writer.Write(">");// Create a script that dynamically associates a new HoverMenuBehavior // with the id of our new div and the ClientID of the popupControl and // register it as a startup scriptstring script =// Wrap everything in a function to keep things uncluttered"<script>(function() { " +// Wrap the wireup in a function to execute on a timeout"var f = function() {" +"var ctrl = new Sys.UI.Control($('" + id +"')); " +"var behavior = new AtlasControlToolkit.HoverMenuBehavior(); " +"behavior.set_PopupControlID('" + popupControl.ClientID +"'); " +"behavior.set_PopupPosition('Right'); " +"ctrl.get_behaviors().add(behavior); " +"behavior.initialize(); " +"}; " +// Wait 1 second before running the function"window.setTimeout(f, 1000); " +"})();</script>"; page.RegisterStartupScript(id, script);// Write out the TreeNodebase.RenderPreText(writer); }/// <summary> /// Write the end of the div that wraps the TreeNode /// </summary> /// <param name="writer">Html Writer</param>protected override void RenderPostText(HtmlTextWriter writer) {base.RenderPostText(writer); writer.WriteEndTag("div"); } }}

Thanks,
Ted


Could most of this plumbing work be handled in an Adapter (ala the CSSAdapters)? Then you could change the way the actual TreeNode is rendered and then implement HoverTreeView class as a derivative of the normal TreeView which could be targetted by the normal extender stuff.

Hi IDisposable,

Yep, a lot of the plumbing goes away if you inherit from a TreeView. I don't even think you'd need to use an adapter. You could dynamically add theHoverMenuExtender to itsControls collection, etc. I believe you'd still be stuck with the problem of wiring up theTargetControlID of theHoverMenuProperties because it needs to be a server control. Not to mention the larger issue of associating any of the content in yourHoverMenu with a givenTreeNodefor any real functionality, etc. Aside from hacking something very specific together, I doubt you'd be able to make a solid, general purpose solution.

Thanks,
Ted


Has anyone come up with a workable way to do this yet? I played around with adding a HoverMenuExtender to a TreeNode programmatically but quickly found out that the TreeNode does not have an ID that I could access. So, therefore, I didn't have anything to poke into the TargetID property of the HoverMenuExtender.

Monday, March 26, 2012

Treeview inside a HoverMenu causes HoverMenu to not dissapear?

I have a treeview inside a hovermenu and if no one selects a treenode then the hovermenu disapears if the mouse leaves the hovermenu area.

However if a treenode IS selected then the hovermenu does NOT disapear when the mouse leaves the hovermenu area.

Is this a focus issue? cause i tried catching the selectednode event and calling .focus() on the treeviews parent but that didnt do anything/

In order to make the hovermenu disapear i have to click the webpage area outside the hovermenu area.

HELP ??

Also if I use Firefox the hovermenu does not disssapear no matter where i click otside the hover area

TreeView inside UpdatePanel, childnode NOT deselecting.

I have a treeview sitting inside a updatepanel that has ChildrenAsTriggers set to false.
On Page_Load, I programmatically selected expanded a treenode and selected a node, ie

treenode.Expand();
childnode.Select();

PROBLEM:

(Highlighted = SelectedNodeStyle)

When i select another node on the page, the node that i selected programmatically stays highlighted.
Therefore, the treeview now has a NEW selected node, but two highlighted node.

Any ideas??



It is not supported ... sorry..

http://ajax.asp.net/docs/overview/UpdatePanelOverview.aspx

The following ASP.NET controls are not compatible with partial-page updates, and are therefore not supported inside an UpdatePanel control:

TreeView and Menu controls.

Web Parts controls. For more information, see ASP.NET Web Parts Pages.

FileUpload controls when they are used to upload files as part of an asynchronous postback.

GridView and DetailsView controls when the EnableSortingAndPagingCallbacks property is set to true. The default is false.

Login, PasswordRecovery, ChangePassword, and CreateUserWizard controls that have not been converted into editable templates.

The Substitution control.

Treeview inside updatepanel postingback on selectednodechanged

Hi,

I'm having problem with a treeview inside an updatepanel on my page. The treeview is populated from the client on the treenode pouplate event. The selection of a node in the treeview triggers the content of another updatepanel to be displayed according to the selected node. Everything works fine exept that the whole tree is postedback on the selectednodechanged event even tough the triggers for that update panel is on treenodepopulate.

Here's the code :

<%-- The treeview --%> <atlas:UpdatePanel ID="uptv" runat="server" mode="conditional" 
<ContentTemplate
<asp:Panel ID="panTree" runat="server" Height="600px" ScrollBars="Auto" Style="z-index: 102;
left: 3px; position:absolute; top:5px;" Width="450px" CssClass="bordures"
<asp:TreeView ID="tvEquipement" runat="server" Height="100%" Style="z-index: 100; left: 0px;
position: absolute; top: 0px" Width="100%" ForeColor="ControlText" ExpandDepth="2" NodeIndent="10"
<SelectedNodeStyle BackColor="#D09200" Font-Bold="True" ForeColor="HighlightText" BorderColor="HighlightText" />
<RootNodeStyle Font-Bold="True" /
</asp:TreeView
</asp:Panel
</ContentTemplate
<Triggers
<atlas:ControlEventTrigger ControlID="tvEquipement" EventName="TreeNodePopulate" /
</Triggers
</atlas:UpdatePanel
<atlas:UpdatePanel ID="upInfos" runat="server" mode="conditional"
<ContentTemplate>
<%-- stuff based on the selected node--%> </ContentTemplate
<Triggers
<asp:ControlEventTrigger ControlID="tvEquipement" EventName="SelectedNodeChanged" /
</Triggers
</atlas:UpdatePanel>

Any hep or idea would be greatly appreciated.

Thanks,

Max

The treeview is inside the update panel and childrenAsTriggers is set to true (Default is true). Therefore, if you click on control inside the update panel it would result in the
update panel getting updated. What you have to do is set ChildrenAsTriggers = false for the update panel with treeview.

On a different note: Treeview inside an update panel is not a supported scenario.

vineetc


Thanks for your reply. I don't seem to have that property. Is this a new feature from the Ajax Beta release. I'm still working with the last Atlas release.

The tree wasn't in an updatepanel at first, but I had to put it in one because the selectedvalue property was messed up when outside the updatepanel.

Max


Ajax beta release has this property. Also Property "Mode" of the update panel is renamed to "UpdateMode".

vineetc