AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=110&pId=-1
Not as easy as it seems: Webform Dynamic Buttons
page
by Matthew Small
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 35251/ 39

The Newbie Problem, Part 1

This article was contributed by Matthew Small and he can be reached at matt@showstopperonline.com

The Newbie Problem Part 1

OK, I am a newbie to Visual Basic.NET. However, I am an experienced programmer, and have used a few languages in my day, including VB 6.0 and C++. I therefore should be able to pick up the syntax of VB.NET pretty easily. Take this for example:

<asp:linkbutton
          commandname="categoryid"
          commandargument="1"
          oncommand="lbLink_Click"
          text="Men’s Clothing" />

The above is the explicit placement of a linkbutton on the webform. Logically, it should be equivalent to this code below:

dim lbLink as new LinkButton
lbLink.Text = "Men’s Clothing"
lbLink.CommandName = "CategoryId"
lbLink.CommandArgument = "1"
lbLink.OnCommand = "lbLink_Click"

However, it is not. When run, this code will generate an error:

BC30390: 'System.Web.UI.WebControls.LinkButton.Protected Overridable Overloads Sub OnCommand(e As System.Web.UI.WebControls.CommandEventArgs)' is not accessible in this context because it is 'Protected'

Line 92:     lbLink.Text = "Men’s Clothing"
Line 93:     lbLink.CommandArgument = "1"
Line 94:     lbLink.OnCommand="lbLink_Click"
Line 95:
Line 96:

Ok, what does that mean? I really don’t know, but I do know that my code won’t work like that. The solution is simple but isn’t found in any of my ASP.NET books.

For reasons beyond my limited knowledge, Microsoft decided that instead of the logical dot-notation for adding a OnClick or OnCommand attribute to our Button, a separate statement was to be required: addhandler

dim lbLink as new LinkButton
lbLink.Text = "Men’s Clothing"
lbLink.CommandName = "CategoryId"
lbLink.CommandArgument = "1"
AddHandler lbLink.Command, AddressOf lbLink_Click

The addhandler statement binds an event to a subroutine or function of your choice. The generic syntax is:

AddHandler event, AddressOf subroutine

For more detailed information on it, go to

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vblr7/html/vastmAddHandlerStatement.asp

OK, that wasn’t so hard. We now have the correct syntax for binding an event to a subroutine or function.

The Newbie Problem Part 2

The Newbie Problem Part 2

The next problem comes when we generate these buttons in a subroutine. One of the first things I did when I started writing Webforms was to use the panels server control to create wizard-like pages. I did this independent of any knowledge that others were doing it, but there is a nice article by Rajiv. R on using this method to create your webforms located at: http://aspalliance.com/articles/panels.aspx

Let’s expand our code a bit:

Sub ChooseCategory (Sender As Object, e as EventArgs)
     pnlSelectCategory.visible = true
     pnlSelectItem.visible = false
     pnlViewItem.visible = false
     pnlViewCart.visible = false
     pnlCheckout.visible = false
     pnlOrderPlaced.visible = false

     'Get database information into my user-defined server control called database...
     'End database information

     dim lbLink as LinkButton
     dim dbRow as System.Data.DataRow

     for each dbRow in database.table("tablename").rows
          lbLink = new LinkButton lbLink.Text = dbrow.item("categoryname")
          lbLink.CommandName = "CategoryId"
          lbLink.CommandArgument = dbrow.item("CategoryId")
          AddHandler lbLink.Command, AddressOf lbLink_Click
          pnlSelectCategoryl.Controls.Add(lbLink)
     next
End Sub

Sub lbLink_Click (Sender As Object, e As CommandEventArgs)
     dim lbLink As LinkButton = CType(Sender, LinkButton)
     dim CategoryId as String = lbLink.CommandArgument
     ' Do things with this information
     ...
End Sub

What the "ChooseCategory" code does (should do) is

1) Set the panel "pnlSelectCategory" to visible
2) Gets information from a database
3) Loops over each row in the database
4) Generates a linkbutton for each category in the database, each of which will call the subroutine lbLink_Click

Ok, everything’s copasetic, right? Not exactly. When this code is executed, no errors will be generated. Your links will be generated nicely, they will be pretty, but they won’t do anything. You can click on them all day and all you will get is a page-repost. They will not fire the event which will run the subroutine lbLink_Click.

What’s the problem? Well the problem lies in the fact that these are dynamically defined, and not permanent web controls. When the page reposts, they are not recognized by the code because at that time, they don’t exist, and therefore will not fire the event to execute the subroutine. How do we fix this problem? Easy: re-create them everytime we create the page, in the page_load subroutine.

Let’s re-write the code:

Sub Page_Load (Sender As Object, e As EventArgs)
     CreateDynamicButtons()
End Sub

Sub CreateDynamicButtons ()

     'Get database information into my user-defined server control called database
     '...
     'End database information

     dim lbLink as LinkButton
     dim dbRow as System.Data.DataRow

     for each dbRow in database.table("tablename").rows
          lbLink = new LinkButton lbLink.Text = dbrow.item("categoryname")
          lbLink.CommandName = "CategoryId"
          lbLink.CommandArgument = dbrow.item("CategoryId")
          AddHandler lbLink.Command, AddressOf lbLink_Click
          pnlSelectCategoryl.Controls.Add(lbLink)
     next
End Sub

Sub ChooseCategory (Sender As Object, e as EventArgs)
     pnlSelectCategory.visible = true
     pnlSelectItem.visible = false
     pnlViewItem.visible = false
     pnlViewCart.visible = false
     pnlCheckout.visible = false
     pnlOrderPlaced.visible = false
End Sub

Sub lbLink_Click (Sender As Object, e As CommandEventArgs)
     dim lbLink As LinkButton = CType(Sender, LinkButton)
     dim CategoryId as String = lbLink.CommandArgument
     ' Do things with this information
     '...
End Sub

Now we have split the ChooseCategory subroutine into two parts that execute independently of each other and inserted a call to CreateDynamicButtons into the Page_Load subroutine. Now whenever the page is loaded, the CreateDynamicButtons subroutine is called, and it creates the buttons so that their events will be recognized by the AddHandler statement.

This article was contributed by Matthew Small and he can be reached at matt@showstopperonline.com

Matthew Small is the IT Supervisor for Showstopper, the national dance competition company located in Murrells Inlet, South Carolina. He was formerly a consultant for Allaire Corp., the creator of the ColdFusion Markup Language (CFML) and now spends his time working on his MIS Master’s Degree and trying to learn everything .NET. He can be reached at mattATShowstopperonline.com.


Product Spotlight
Product Spotlight 

©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-24 12:19:26 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search