I've been trying all day to get this to work and I am fed up. I just can't get it to render correctly. For whatever reason my code is cramming everything into one pane. Someone please take a look at my code and point me in the right direction.
Protected Sub AccordionSiteMap_Load(ByVal sender As Object, ByVal e As EventArgs)
Dim p As New AjaxControlToolkit.AccordionPane
If SiteMap.RootNode.HasChildNodes Then
Dim RootNodesEnumerator As IEnumerator = SiteMap.RootNode.ChildNodes.GetEnumerator()
Dim nodeTxt As String = ""
Dim accCtrl As New LiteralControl
Dim HeaderClass As String = "AccordionHeader"
Dim ContentClass As String = "AccordionContent"
Dim paneCounter As Integer = 0
While RootNodesEnumerator.MoveNext
With p.HeaderContainer.Controls
.Add(New LiteralControl("<div class='"))
.Add(New LiteralControl(HeaderClass))
.Add(New LiteralControl("'><a href=''>"))
.Add(New LiteralControl(RootNodesEnumerator.Current.title))
.Add(New LiteralControl("</a></div>"))
End With
If RootNodesEnumerator.Current.HasChildNodes Then
Dim ChildNodesEnumerator As IEnumerator = RootNodesEnumerator.Current.ChildNodes.GetEnumerator()
With p.ContentContainer.Controls
.Add(New LiteralControl("<div class='"))
.Add(New LiteralControl(ContentClass))
.Add(New LiteralControl("'>"))
While ChildNodesEnumerator.MoveNext
.Add(New LiteralControl("<a href='"))
.Add(New LiteralControl(ChildNodesEnumerator.Current.url))
.Add(New LiteralControl("'>"))
.Add(New LiteralControl(ChildNodesEnumerator.Current.title))
.Add(New LiteralControl("</a><br />"))
End While
.Add(New LiteralControl("</div>"))
End With
End If
AccordionSiteMap.Panes.Add(p)
End While
End If
Remember: mark posts that helped you as the answer to aid future readers
Well anyone who is familiar with VB.Net should spot my mistake pretty quickly. However, it has been a while since I've done any coding. Let alone with VB. I am more of a C guy. Which begs the question, why don't I use C#? Well, I'm lazy and case sensitivity
and all that type casting seems like to much of a pain the ass.
But alas, after a good night's rest, I remember a little thing about the behavior of objects and realized my problem lay in the p object. So I added the following lines at the beginning of my first While loop:
p = Nothing
p = New AjaxControlToolkit.AccordionPane
And low and behold it works now! But if anyone can spot a better way, please let me know.
Remember: mark posts that helped you as the answer to aid future readers
Just in case in the future someone is looking to make the Accordion control into a sitemap also I am going to post my final code. Well, it's probably not completely final, but its working beatifully and it looks freakin awesome! Sorry for the lack of comments
in the code.
The AccordianSiteMap_Load() is called during the Page_Load event and parses the SiteMap collection to fill the Accordion panes.
The AccordionSiteMap_OpenCurrentPane(), also called from Page_Load, opens the current pages pane in the Accordian control when the current page changes. It does this with the help of RootIndexofCurrentNode() which searches through the SiteMap collection
to determine which pane the current page belongs to. A warning about this function though, if your SiteMap tree is very deep this function might slow your page load times down. It is a recursive function so depending on the depth of your sitemap the times
will vary. My SiteMap is only 3 levels deep and the time isn't even noticeable.
Also, I'd like to say, I haven't done any programming in quite a long time (3 years) and I am quite proud of myself for remembering how to code recursion (compiled and ran properly on first try), but if anyone has any suggestions or spots a mistake anywhere
in my code please let me know!
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
AccordionSiteMap_Load(sender, e)
AccordionSiteMap_OpenCurrentPane(sender, e)
End Sub
Protected Sub AccordionSiteMap_Load(ByVal sender As Object, ByVal e As EventArgs)
Dim p As New AjaxControlToolkit.AccordionPane
Dim linkClass, currentLinkClass, nonCurrentLinkClass As String
linkClass = ""
currentLinkClass = "AccordionCurrentLink"
nonCurrentLinkClass = "AccordionLink"If SiteMap.RootNode.HasChildNodes Then
Dim RootNodesEnumerator As IEnumerator = SiteMap.RootNode.ChildNodes.GetEnumerator()
Dim paneCounter As Integer = 0
While RootNodesEnumerator.MoveNext
p = Nothing
p = New AjaxControlToolkit.AccordionPane
p.ID = "Pane" & Regex.Replace(RootNodesEnumerator.Current.ToString(), "\s+", "")
p.HeaderContainer.Controls.Add(New LiteralControl("<span>" & RootNodesEnumerator.Current.Title & "</span>"))
If RootNodesEnumerator.Current.HasChildNodes Then
Dim ChildNodesEnumerator As IEnumerator = RootNodesEnumerator.Current.ChildNodes.GetEnumerator()
While ChildNodesEnumerator.MoveNext
If SiteMap.CurrentNode Is Nothing Then
linkClass = nonCurrentLinkClass
ElseIf SiteMap.CurrentNode.ToString = ChildNodesEnumerator.Current.ToString Then
linkClass = currentLinkClass
Else
linkClass = nonCurrentLinkClass
End If
p.ContentContainer.Controls.Add(New LiteralControl("<a class='" & linkClass & "' "))
p.ContentContainer.Controls.Add(New LiteralControl("href='" & ChildNodesEnumerator.Current.url & "'>"))
p.ContentContainer.Controls.Add(New LiteralControl(ChildNodesEnumerator.Current.title & "</a>"))
End While
End If
AccordionSiteMap.Panes.Add(p)
End While
End If
End Sub
Protected Sub AccordionSiteMap_OpenCurrentPane(ByVal sender As Object, ByVal e As EventArgs)
If SiteMap.CurrentNode Is Nothing Then
AccordionSiteMap.SelectedIndex = -1
Else
AccordionSiteMap.SelectedIndex = RootIndexofCurrentNode(SiteMap.RootNode.ChildNodes)
End If
End Sub
Private Function RootIndexofCurrentNode(ByVal Nodes As SiteMapNodeCollection) As Short
Dim index As Short = -2
If Nodes Is Nothing Then
RootIndexofCurrentNode = -1
ElseIf Nodes.Contains(SiteMap.CurrentNode) Then
RootIndexofCurrentNode = Nodes.IndexOf(SiteMap.CurrentNode)
Else
For Each n As SiteMapNode In Nodes
index = RootIndexofCurrentNode(n.ChildNodes)
If index <> -1 Then
If n.ParentNode.ToString = SiteMap.RootNode.ToString Then
Return SiteMap.RootNode.ChildNodes.IndexOf(n)
Else
Return index
End If
End If
Next
Return -1
End If
Here's a screenshot of what it looks like. I don't have the site online yet so this is the best I can do. And ignore the dumb content in the main window.
SCREENSHOT1
Remember: mark posts that helped you as the answer to aid future readers
For those of you who want to know how to do this in C# here is what I used. Granted the menu is fairly simple, but it works like a charm and seems like a bit less coding.
Ya ya. It is a little bit less coding :P But the extra functions in my code will make sure the pane containing the current page will be open after the page is loaded.
I've converted all my code to C# now too. Man am I glad to be done with VB (fingers crossed).
I'll probably post it a little later after I see if I can make some optimizations based on your version.
Thanks.
Remember: mark posts that helped you as the answer to aid future readers
[:D] I now have a version that will make sure the appropriate pane is open when the page is loaded. I had to make some tweaks to get my code to work with a dynamic sitemap pulled from an SQL database, but it's working now. Sometime I'll post my code again
as well. [:D]
For instance, in the screenshot posted, lets say the Elevator section had more sections underneath it. Would they also expand in another accordion control?
As far as my example goes, no it does not support more than 1 level under it as an accordion control. You can still have a menu control load withing the accordion control or just a few indented bulleted lists. The way the accordion control is designed,
it doesn't work with the idea of having more than a 2-tier menu. a 3-tier or more menu would need something other than an accordion control.
Of course, having said all of this, you could insert another accordion control within the first to handle the 3rd and/or 4th tiers... but it is then a seperate object and not part of the first at all. other than location on the page of course.
Don't know how well it would perform in IE though. It would basically require nested Accordions within each pane. IE already has questionable performance with this control.
I was using a lot of PNG images to style it though and found that IE doesn't like 1px wide/tall PNGs. It likes larger blocks. Once I increased the size of the repeating PNG background images the performance got a lot better. But it still takes 20% cpu sometimes
to expand or shrink a pane.
If you don't want the expand-a-shrink-a-bility in your sub-sub nodes you could just do it as a <ul> in the pane I guess. But that's probably not the effect you're looking for.
Remember: mark posts that helped you as the answer to aid future readers
whatispunk
Contributor
4074 Points
876 Posts
Accordion as a sitemap
Mar 28, 2007 12:07 AM|LINK
I've been trying all day to get this to work and I am fed up. I just can't get it to render correctly. For whatever reason my code is cramming everything into one pane. Someone please take a look at my code and point me in the right direction.
Protected Sub AccordionSiteMap_Load(ByVal sender As Object, ByVal e As EventArgs)
Dim p As New AjaxControlToolkit.AccordionPane
If SiteMap.RootNode.HasChildNodes Then
Dim RootNodesEnumerator As IEnumerator = SiteMap.RootNode.ChildNodes.GetEnumerator()
Dim nodeTxt As String = ""
Dim accCtrl As New LiteralControl
Dim HeaderClass As String = "AccordionHeader"
Dim ContentClass As String = "AccordionContent"
Dim paneCounter As Integer = 0
While RootNodesEnumerator.MoveNext
p.ID = "Pane" & Regex.Replace(RootNodesEnumerator.Current.ToString(), "\s+", "")
With p.HeaderContainer.Controls
.Add(New LiteralControl("<div class='"))
.Add(New LiteralControl(HeaderClass))
.Add(New LiteralControl("'><a href=''>"))
.Add(New LiteralControl(RootNodesEnumerator.Current.title))
.Add(New LiteralControl("</a></div>"))
End With
If RootNodesEnumerator.Current.HasChildNodes Then
Dim ChildNodesEnumerator As IEnumerator = RootNodesEnumerator.Current.ChildNodes.GetEnumerator()
With p.ContentContainer.Controls
.Add(New LiteralControl("<div class='"))
.Add(New LiteralControl(ContentClass))
.Add(New LiteralControl("'>"))
While ChildNodesEnumerator.MoveNext
.Add(New LiteralControl("<a href='"))
.Add(New LiteralControl(ChildNodesEnumerator.Current.url))
.Add(New LiteralControl("'>"))
.Add(New LiteralControl(ChildNodesEnumerator.Current.title))
.Add(New LiteralControl("</a><br />"))
End While
.Add(New LiteralControl("</div>"))
End With
End If
AccordionSiteMap.Panes.Add(p)
End While
End If
Why UpdatePanels Are Dangerous
Why You Should Not Place Your Whole Site In An UpdatePanel
whatispunk
Contributor
4074 Points
876 Posts
Re: Accordion as a sitemap
Mar 28, 2007 01:04 PM|LINK
Well anyone who is familiar with VB.Net should spot my mistake pretty quickly. However, it has been a while since I've done any coding. Let alone with VB. I am more of a C guy. Which begs the question, why don't I use C#? Well, I'm lazy and case sensitivity and all that type casting seems like to much of a pain the ass.
But alas, after a good night's rest, I remember a little thing about the behavior of objects and realized my problem lay in the p object. So I added the following lines at the beginning of my first While loop:
p = Nothing
p = New AjaxControlToolkit.AccordionPane
And low and behold it works now! But if anyone can spot a better way, please let me know.
Why UpdatePanels Are Dangerous
Why You Should Not Place Your Whole Site In An UpdatePanel
whatispunk
Contributor
4074 Points
876 Posts
Re: Accordion as a sitemap
Mar 28, 2007 09:33 PM|LINK
Just in case in the future someone is looking to make the Accordion control into a sitemap also I am going to post my final code. Well, it's probably not completely final, but its working beatifully and it looks freakin awesome! Sorry for the lack of comments in the code.
The AccordianSiteMap_Load() is called during the Page_Load event and parses the SiteMap collection to fill the Accordion panes.
The AccordionSiteMap_OpenCurrentPane(), also called from Page_Load, opens the current pages pane in the Accordian control when the current page changes. It does this with the help of RootIndexofCurrentNode() which searches through the SiteMap collection to determine which pane the current page belongs to. A warning about this function though, if your SiteMap tree is very deep this function might slow your page load times down. It is a recursive function so depending on the depth of your sitemap the times will vary. My SiteMap is only 3 levels deep and the time isn't even noticeable.
Also, I'd like to say, I haven't done any programming in quite a long time (3 years) and I am quite proud of myself for remembering how to code recursion (compiled and ran properly on first try), but if anyone has any suggestions or spots a mistake anywhere in my code please let me know!
' HTML
' VB CODE
'CSS
Here's a screenshot of what it looks like. I don't have the site online yet so this is the best I can do. And ignore the dumb content in the main window.
SCREENSHOT1
Why UpdatePanels Are Dangerous
Why You Should Not Place Your Whole Site In An UpdatePanel
Stoutheart
Member
36 Points
19 Posts
Re: Accordion as a sitemap
Sep 22, 2007 04:17 PM|LINK
For those of you who want to know how to do this in C# here is what I used. Granted the menu is fairly simple, but it works like a charm and seems like a bit less coding.
Aspx page
<asp:ScriptManager ID="ScriptManager1" runat="server" /> <div> <h4>Dynamic Accordion Menu</h4> <cc1:Accordion ID="myAccordion" runat="server" SuppressHeaderPostbacks="true" > </cc1:Accordion> </div>CodeFile:
accordion sitemap c#
* Stoutheart *
**************
whatispunk
Contributor
4074 Points
876 Posts
Re: Accordion as a sitemap
Nov 27, 2007 02:34 AM|LINK
Ya ya. It is a little bit less coding :P But the extra functions in my code will make sure the pane containing the current page will be open after the page is loaded.
I've converted all my code to C# now too. Man am I glad to be done with VB (fingers crossed).
I'll probably post it a little later after I see if I can make some optimizations based on your version.
Thanks.
Why UpdatePanels Are Dangerous
Why You Should Not Place Your Whole Site In An UpdatePanel
Stoutheart
Member
36 Points
19 Posts
Re: Accordion as a sitemap
Nov 27, 2007 12:03 PM|LINK
[:D] I now have a version that will make sure the appropriate pane is open when the page is loaded. I had to make some tweaks to get my code to work with a dynamic sitemap pulled from an SQL database, but it's working now. Sometime I'll post my code again as well. [:D]
* Stoutheart *
**************
TCavins
Member
718 Points
213 Posts
Re: Accordion as a sitemap
Nov 27, 2007 02:53 PM|LINK
Does this handle multiple levels?
For instance, in the screenshot posted, lets say the Elevator section had more sections underneath it. Would they also expand in another accordion control?
Tim
Stoutheart
Member
36 Points
19 Posts
Re: Accordion as a sitemap
Nov 27, 2007 03:43 PM|LINK
As far as my example goes, no it does not support more than 1 level under it as an accordion control. You can still have a menu control load withing the accordion control or just a few indented bulleted lists. The way the accordion control is designed, it doesn't work with the idea of having more than a 2-tier menu. a 3-tier or more menu would need something other than an accordion control.
Of course, having said all of this, you could insert another accordion control within the first to handle the 3rd and/or 4th tiers... but it is then a seperate object and not part of the first at all. other than location on the page of course.
Does this make sense?
* Stoutheart *
**************
whatispunk
Contributor
4074 Points
876 Posts
Re: Accordion as a sitemap
Nov 27, 2007 03:43 PM|LINK
Not at the present, but it could be done.
Don't know how well it would perform in IE though. It would basically require nested Accordions within each pane. IE already has questionable performance with this control.
I was using a lot of PNG images to style it though and found that IE doesn't like 1px wide/tall PNGs. It likes larger blocks. Once I increased the size of the repeating PNG background images the performance got a lot better. But it still takes 20% cpu sometimes to expand or shrink a pane.
If you don't want the expand-a-shrink-a-bility in your sub-sub nodes you could just do it as a <ul> in the pane I guess. But that's probably not the effect you're looking for.
Why UpdatePanels Are Dangerous
Why You Should Not Place Your Whole Site In An UpdatePanel
Anneleen
Member
24 Points
38 Posts
Re: Accordion as a sitemap
May 01, 2008 01:27 PM|LINK
Hi Thank you for this code it's really useful. But I wanted to make from the headers of the accordionpane also links
I changed the code to this
p.HeaderContainer.Controls.Add(New LiteralControl("<a href='" & RootNodesEnumerator.Current.url & "'><span>" & RootNodesEnumerator.Current.Title & "</span></a>"))
But this doesn't work
What do I wrong?
Greets
Anneleen