views:

235

answers:

2

I extended treeview, treenode, and nodetype so I could have custom nodes. Certain nodes have image buttons on them allowing them to add a child node or delete the node. I can't handle any of the events from my buttons.

Public Class ContentTreeView
Inherits TreeView

Public Event OnAddChild(ByVal sender As Object, ByVal e As EventArgs)
Public Event OnDelete(ByVal sender As Object, ByVal e As EventArgs)

Private _AddImageURL As String = String.Empty
Private _DeleteImageURL As String = String.Empty

Public Property AddImageURL() As String
    Get
        Return _AddImageURL
    End Get
    Set(ByVal value As String)
        _AddImageURL = value
    End Set
End Property

Public Property DeleteImageURL() As String
    Get
        Return _DeleteImageURL
    End Get
    Set(ByVal value As String)
        _DeleteImageURL = value
    End Set
End Property

Protected Overrides Function CreateNode() As TreeNode
    Dim retval As ContentTreeNode = New ContentTreeNode(AddImageURL, DeleteImageURL)
    AddHandler retval.OnAddChild, AddressOf ContentNode_AddChild
    AddHandler retval.OnDelete, AddressOf ContentNode_Delete
    Return retval
End Function

Protected Sub ContentNode_AddChild(ByVal sender As Object, ByVal e As EventArgs)
    RaiseEvent OnAddChild(Nothing, Nothing)
End Sub
Protected Sub ContentNode_Delete(ByVal sender As Object, ByVal e As EventArgs)
    RaiseEvent OnDelete(Nothing, Nothing)
End Sub

Public Class ContentTreeNode
    Inherits TreeNode

    Public Event OnAddChild(ByVal sender As Object, ByVal e As EventArgs)
    Public Event OnDelete(ByVal sender As Object, ByVal e As EventArgs)

    Private _AddImageURL As String = String.Empty
    Private _DeleteImageURL As String = String.Empty

    Private btnAddChild As ImageButton
    Private btnDelete As ImageButton

    Public Sub New(ByVal AddImageURL_ As String, ByVal DeleteImageURL_ As String)
        _AddImageURL = AddImageURL_
        _DeleteImageURL = DeleteImageURL_
    End Sub

    Public Property AddImageURL() As String
        Get
            Return _AddImageURL
        End Get
        Set(ByVal value As String)
            _AddImageURL = value
        End Set
    End Property

    Public Property DeleteImageURL() As String
        Get
            Return _DeleteImageURL
        End Get
        Set(ByVal value As String)
            _DeleteImageURL = value
        End Set
    End Property

    Protected Overrides Sub RenderPreText(ByVal writer As HtmlTextWriter)
    End Sub

    Protected Overrides Sub RenderPostText(ByVal writer As HtmlTextWriter)
        CreateChildControls()
        If GetTreeNodeType() <> ContentTreeNodeTypes.Root Then
            btnAddChild.RenderControl(writer)
            If GetTreeNodeType() <> ContentTreeNodeTypes.Category Then
                btnDelete.RenderControl(writer)
            End If
        End If
    End Sub

    Private Function GetTreeNodeType() As TreeNodeTypes
        Dim leaf As TreeNodeTypes = TreeNodeTypes.Leaf
        If ((Me.Depth = 0) AndAlso (Me.ChildNodes.Count > 0)) Then
            Return ContentTreeNodeTypes.Root
        End If
        If Me.Depth = 1 Then
            Return ContentTreeNodeTypes.Category
        End If
        If ((Me.ChildNodes.Count <= 0) AndAlso Not Me.PopulateOnDemand) Then
            Return leaf
        End If
        Return ContentTreeNodeTypes.Parent
    End Function

    Protected Sub CreateChildControls()
        'Controls.Clear()

        '***Creat Add Button***
        btnAddChild = New ImageButton()
        btnAddChild.ID = "btnAddChild"
        btnAddChild.ImageUrl = AddImageURL
        btnAddChild.ToolTip = "Add Child"
        AddHandler btnAddChild.Click, AddressOf btnAddChild_Click

        '***Create DeleteButton***
        btnDelete = New ImageButton()
        btnDelete.ID = "btnDelete"
        btnDelete.ImageUrl = DeleteImageURL()
        btnDelete.ToolTip = "Delete Page"
        AddHandler btnDelete.Click, AddressOf btnDelete_Click

        ''***Add Controls***
        'Me.Controls.Add(btnAddChild)
        'Me.Controls.Add(btnDelete)
    End Sub

    Protected Sub btnAddChild_Click(ByVal sender As Object, ByVal e As EventArgs)
        RaiseEvent OnAddChild(Nothing, Nothing)
    End Sub
    Protected Sub btnDelete_Click(ByVal sender As Object, ByVal e As EventArgs)
        RaiseEvent OnDelete(Nothing, Nothing)
    End Sub


    Public Enum ContentTreeNodeTypes
        All = 7
        Leaf = 4
        None = 0
        Parent = 2
        Root = 1
        Category = 3
    End Enum
End Class

End Class

1) Can I implement something like IPostBackEventHandler? 2) Is this possible since treeNode isn't a control/webcontrol?

Any help is appreciated... Thanks!!!

A: 

I think the problem is timing related, meaning the child controls are added to late in the ASP.Net page lifecycle for the event to be executed.

This might solve the issue:

  1. Compose the whole tree structure as early as possible, e.g. in the Init event of the page.
  2. Append the child ImageButton in the constructor of the ContentTreeNode.

Alternatively you could use a javascript context-menu so you wouldn't need to append any child-controls to the TreeNode...

Vinz
I think you may be right but since the treenodes are added/created when databound I can't really do much about it.
Mike
A: 

After reading this post. I decided to use the following solution. First I changed my CreateChildControls method to:

        Protected Sub CreateChildControls()
        Dim page As Page = HttpContext.Current.CurrentHandler
        Dim csm As ClientScriptManager = page.ClientScript
        Dim control As WebControl = page.Master.FindControl(_ContainerID).FindControl(_ContentTreeViewID)

        '***Creat Add Button***
        btnAddChild = New ImageButton()
        btnAddChild.ID = "btnAddChild"
        btnAddChild.ImageUrl = AddImageURL
        btnAddChild.ToolTip = "Add Child"            
        btnAddChild.Attributes.Add("onClick", csm.GetPostBackEventReference(control, String.Format("{0}:{1}", Me.Value, "Add")))

        '***Create DeleteButton***
        btnDelete = New ImageButton()
        btnDelete.ID = "btnDelete"
        btnDelete.ImageUrl = DeleteImageURL()
        btnDelete.ToolTip = "Delete Page"
        btnDelete.Attributes.Add("onClick", csm.GetPostBackEventReference(control, String.Format("{0}:{1}", Me.Value, "Delete")))
    End Sub

Then I had to implement IPostBackEventHandler in the custom treeview to handle the postback events. Maybe not the best solution but it works well with custom event args.

Mike