Well, I think I finally was able to come up with something. I would like your opinions on the design and if
any improvments/design changes could make this more efficient or practical in real life scenarios. I'm fairly new to asp.net so I'm sure there is probably a much better way to accomplish this but this works for me for right now. Here is my code.. It's a
user control. I tested it 5 levels deep
Imports Microsoft.VisualBasic
Imports AjaxControlToolkit
Imports System.Xml
''' <summary>
''' MultilevelAccordion builds an AjaxControlToolkit Accordion nested specified levels deep
''' The nested levels is Data driven by an XML element called <XMLFILE>name_of_file.xml</XMLFILE>
''' During Item DataBound if it finds an XML element called <XMLFILE></XMLFILE> this is trigger
''' to create a new Sub Accordion. The specified <XMLFILE>name_of_file.xml</XMLFILE> would contain the
''' headers and content info for the sub accordion.
''' </summary>
''' <remarks></remarks>
'''
Public Class MultilevelAccordion
Inherits System.Web.UI.UserControl
''' <summary>
''' Counter added to Sub Accordion IDS to avoid duplicate ID errors
''' </summary>
''' <remarks></remarks>
Private _count As Integer = 1
Private _doc As New XmlDocument
' Xml file passed in to User Control
Public xml As String
' XPATH
Public Xp As String
' Contains current Datasource
Private _currentDataSource As Object
''' <summary>
''' Public Property to set XmlFile
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property XmlFile() As String
Get
Return Me.xml
End Get
Set(ByVal value As String)
Me.xml = value
End Set
End Property
''' <summary>
''' Public Poperty to set XPATH of Datasource
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property XmlXpath() As String
Get
Return Me.Xp
End Get
Set(ByVal value As String)
Me.Xp = value
End Set
End Property
''' <summary>
''' Item_Databinding. Called by Parent accordion and all sub Accordions during Item Databinding
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Sub Item_DataBinding(ByVal sender As Object, ByVal e As AccordionItemEventArgs)
Dim currentAcc As Accordion = DirectCast(sender, Accordion)
Dim itemNode As XmlNode = DirectCast(e.AccordionItem.DataItem, XmlNode)
Dim headerLabel As Label
If e.AccordionItem.ItemType = AjaxControlToolkit.AccordionItemType.Header Then
headerLabel = DirectCast(e.AccordionItem.FindControl("AccordionHeader"), Label)
headerLabel.Text = itemNode.SelectSingleNode("DISPLAY").InnerText
End If
If e.AccordionItem.ItemType = AjaxControlToolkit.AccordionItemType.Content Then
' Test if we need to create a Sub Accordion
Dim objtest = itemNode.SelectSingleNode("XMLFILE")
If Not (objtest Is Nothing) Then
' Define Sub Accordion
Dim accSub As New Accordion
accSub.ID = "SubAccordion" + _count.ToString
accSub.HeaderCssClass = "accordionHeader"
accSub.ContentCssClass = "accordionContent"
accSub.RequireOpenedPane = "false"
' Don't want any open panes on load
accSub.SelectedIndex = "-1"
accSub.SuppressHeaderPostbacks = "true"
accSub.HeaderCssClass = "accordionHeader"
accSub.HeaderSelectedCssClass = "accordionHeaderSelected"
accSub.ContentCssClass = "accordionContent"
accSub.HeaderTemplate = New AccordionTemplate(AccordionItemType.Header)
accSub.ContentTemplate = New AccordionTemplate(AccordionItemType.Content)
' Load Xml File
_doc.Load(Server.MapPath("~") + "\Xml\" + objtest.InnerText)
_currentDataSource = _doc.SelectNodes(XmlXpath())
' Set DataSource for Sub Accordion
accSub.DataSource = _currentDataSource
AddHandler accSub.ItemDataBound, New EventHandler(Of AccordionItemEventArgs)(AddressOf Item_DataBinding)
currentAcc.Panes.Item(currentAcc.Panes.Count - 1).ContentContainer.Controls.Add(accSub)
' Increment Counter
_count += 1
accSub.DataBind()
Else
currentAcc.Panes.Item(currentAcc.Panes.Count - 1).ContentContainer.Controls.Add(New LiteralControl("<p>hello</p>"))
'build content
End If
End If
End Sub
''' <summary>
'''
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
accComplexData.HeaderTemplate = New AccordionTemplate(AccordionItemType.Header)
accComplexData.ContentTemplate = New AccordionTemplate(AccordionItemType.Header)
' Load xml for Accordion,
' set _currentDataSource for Accordion and
' bind Accordion to Data Source
_doc.Load(Server.MapPath("~") + "\Xml\" + XmlFile())
_currentDataSource = _doc.SelectNodes(XmlXpath())
accComplexData.DataSource = _currentDataSource
accComplexData.DataBind()
End Sub
End Class
davide128
Member
80 Points
155 Posts
Re: Create databound nested ajax toolkit accordion programatically(In code Behind)
Sep 01, 2010 12:24 PM|LINK
Well, I think I finally was able to come up with something. I would like your opinions on the design and if
any improvments/design changes could make this more efficient or practical in real life scenarios. I'm fairly new to asp.net so I'm sure there is probably a much better way to accomplish this but this works for me for right now. Here is my code.. It's a user control. I tested it 5 levels deep
Imports Microsoft.VisualBasic Imports AjaxControlToolkit Imports System.Xml ''' <summary> ''' MultilevelAccordion builds an AjaxControlToolkit Accordion nested specified levels deep ''' The nested levels is Data driven by an XML element called <XMLFILE>name_of_file.xml</XMLFILE> ''' During Item DataBound if it finds an XML element called <XMLFILE></XMLFILE> this is trigger ''' to create a new Sub Accordion. The specified <XMLFILE>name_of_file.xml</XMLFILE> would contain the ''' headers and content info for the sub accordion. ''' </summary> ''' <remarks></remarks> ''' Public Class MultilevelAccordion Inherits System.Web.UI.UserControl ''' <summary> ''' Counter added to Sub Accordion IDS to avoid duplicate ID errors ''' </summary> ''' <remarks></remarks> Private _count As Integer = 1 Private _doc As New XmlDocument ' Xml file passed in to User Control Public xml As String ' XPATH Public Xp As String ' Contains current Datasource Private _currentDataSource As Object ''' <summary> ''' Public Property to set XmlFile ''' </summary> ''' <value></value> ''' <returns></returns> ''' <remarks></remarks> Public Property XmlFile() As String Get Return Me.xml End Get Set(ByVal value As String) Me.xml = value End Set End Property ''' <summary> ''' Public Poperty to set XPATH of Datasource ''' </summary> ''' <value></value> ''' <returns></returns> ''' <remarks></remarks> Public Property XmlXpath() As String Get Return Me.Xp End Get Set(ByVal value As String) Me.Xp = value End Set End Property ''' <summary> ''' Item_Databinding. Called by Parent accordion and all sub Accordions during Item Databinding ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks></remarks> Sub Item_DataBinding(ByVal sender As Object, ByVal e As AccordionItemEventArgs) Dim currentAcc As Accordion = DirectCast(sender, Accordion) Dim itemNode As XmlNode = DirectCast(e.AccordionItem.DataItem, XmlNode) Dim headerLabel As Label If e.AccordionItem.ItemType = AjaxControlToolkit.AccordionItemType.Header Then headerLabel = DirectCast(e.AccordionItem.FindControl("AccordionHeader"), Label) headerLabel.Text = itemNode.SelectSingleNode("DISPLAY").InnerText End If If e.AccordionItem.ItemType = AjaxControlToolkit.AccordionItemType.Content Then ' Test if we need to create a Sub Accordion Dim objtest = itemNode.SelectSingleNode("XMLFILE") If Not (objtest Is Nothing) Then ' Define Sub Accordion Dim accSub As New Accordion accSub.ID = "SubAccordion" + _count.ToString accSub.HeaderCssClass = "accordionHeader" accSub.ContentCssClass = "accordionContent" accSub.RequireOpenedPane = "false" ' Don't want any open panes on load accSub.SelectedIndex = "-1" accSub.SuppressHeaderPostbacks = "true" accSub.HeaderCssClass = "accordionHeader" accSub.HeaderSelectedCssClass = "accordionHeaderSelected" accSub.ContentCssClass = "accordionContent" accSub.HeaderTemplate = New AccordionTemplate(AccordionItemType.Header) accSub.ContentTemplate = New AccordionTemplate(AccordionItemType.Content) ' Load Xml File _doc.Load(Server.MapPath("~") + "\Xml\" + objtest.InnerText) _currentDataSource = _doc.SelectNodes(XmlXpath()) ' Set DataSource for Sub Accordion accSub.DataSource = _currentDataSource AddHandler accSub.ItemDataBound, New EventHandler(Of AccordionItemEventArgs)(AddressOf Item_DataBinding) currentAcc.Panes.Item(currentAcc.Panes.Count - 1).ContentContainer.Controls.Add(accSub) ' Increment Counter _count += 1 accSub.DataBind() Else currentAcc.Panes.Item(currentAcc.Panes.Count - 1).ContentContainer.Controls.Add(New LiteralControl("<p>hello</p>")) 'build content End If End If End Sub ''' <summary> ''' ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks></remarks> Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load accComplexData.HeaderTemplate = New AccordionTemplate(AccordionItemType.Header) accComplexData.ContentTemplate = New AccordionTemplate(AccordionItemType.Header) ' Load xml for Accordion, ' set _currentDataSource for Accordion and ' bind Accordion to Data Source _doc.Load(Server.MapPath("~") + "\Xml\" + XmlFile()) _currentDataSource = _doc.SelectNodes(XmlXpath()) accComplexData.DataSource = _currentDataSource accComplexData.DataBind() End Sub End Class