Published:
21 Oct 2003
|
Abstract
Solutions to two problems developing dynamic buttons for those switching to VB.NET from VB and/or C++: binding an event to a subroutine or function and generating buttons in a subroutine. |
|
by Matthew Small
Feedback
|
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days):
35271/
24
|
|
|
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. |
|
|
User Comments
Title:
Thank you
Name:
Dimitris Kouzoudis
Date:
2010-10-18 4:30:48 AM
Comment:
Great article, solved my problem! I was working on asp.table with dynamic link buttons and faced the same (both) problems with the buttons
|
Title:
Good, but...
Name:
Helvin
Date:
2009-02-10 3:41:44 AM
Comment:
Hey, thanks for pointing out this problem. I thought something was wrong with my code, and this is it. However, I am trying to display the results of a search, which would depend on the search string. So I cant just call my submit_search sub in page_load. (The results of the search include links, which calls another sub, so my situation is similar to yours.)
|
Title:
Grand!
Name:
ElToro
Date:
2007-03-22 5:14:09 PM
Comment:
Finally an article on Panel worth reading! THX!
|
Title:
I get an error
Name:
Andrew
Date:
2007-01-31 7:16:32 AM
Comment:
Testing the code, I get an error saying "'Command' is not an event of System.Object" for the codeline "AddHandler lbLink.Command, AddressOf lbLink_Click". Any clues to what's wrong? My test code is as below:
Dim i As Integer For i = 0 To 20
Dim tr As New TableRow Dim tc = New TableCell Dim lbLink = New LinkButton lbLink.Text = i lbLink.CommandName = "CategoryId" lbLink.CommandArgument = i AddHandler lbLink.Command, AddressOf lbLink_Click tc.Controls.Add(lbLink) tr.Cells.Add(tc) Table1.Rows.Add(tr) Debug.WriteLine(i) Next i
|
Title:
thanks
Name:
Kristof Heyrman
Date:
2007-01-19 4:55:00 AM
Comment:
Thanks man, Your article was very usefull to me. I didn't know how to give an extra parameter (argument) to the button_click function, eg. the tableRow number in a dataset. piece of cake with the Button.commandArgument option.
kind regards Kristof
|
Title:
Grateful
Name:
Diane
Date:
2006-10-23 6:42:21 PM
Comment:
Have been searching for days on how to do this... I'm too much of a newbie to understand most of the things I saw (which I suspect didn't actually tell me this anyway). This was hard, too, but you're CLEAR so I could follow. Thankyou Thankyou Thankyou.
|
Title:
Thank you!
Name:
Phil Strachan
Date:
2006-09-16 11:30:09 PM
Comment:
Thanks a bunch - part 1 was a life saver...late night, deadline looming - you know the drill. Thanks again!
|
Title:
Thanks
Name:
Alex
Date:
2006-08-22 2:55:59 PM
Comment:
Thanks so much man. I decided to just dive into .net by building my own wed control and I couldn’t find a simple solution to do a post back to the control since all the examples use c# which seems to accept the syntax of linkbutton.command. Seeing the line AddHandler lbLink.Command, AddressOf lbLink_Click here saved me hours of banging my head against the desk
|
Title:
Some what confuse
Name:
Sudhir Kumar Jena
Date:
2006-04-03 1:49:31 AM
Comment:
Sir, I am some what confuse with this artical.Can you please explain me clearly. 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
This code is bit confuse.How we get that choosegatagory.If possible pl send me complete code bcoz i want immediatly. thanking You sudhirkumar_jena@yahoo.co.in
|
|
Product Spotlight
|
|