Watch videos with subtitles in your language, upload your videos, create your own subtitles! Click here to learn more on "how to Dotsub"

How To Dynamically Add Controls to a Web Page

0 (0 Likes / 0 Dislikes)
  • Embed Video

  • Embed normal player Copy to Clipboard
  • Embed a smaller player Copy to Clipboard
  • Advanced Embedding Options
  • Embed Video With Transcription

  • Embed with transcription beside video Copy to Clipboard
  • Embed with transcription below video Copy to Clipboard
  • Embed transcript

  • Embed transcript in:
    Copy to Clipboard
  • Invite a user to Dotsub
[Microsoft ] [] [male speaker] In this video I'm going to demonstrate a technique that you can use to allow you to dynamically add an indeterminate number of controls to your web page. To get started I'm going to load a running version of this application, and the reason that I'm going—I want to show you the application first is that you would thinks this would be a fairly straight forward thing to do, but, in fact, there are some necessary tricks in order to get this to work, as you would expect. So just to show you what our end goal is going to be, we've got a collection of controls here, and I can fill them in with text. If I say add a text box I get another one, and if I say get values we go out and iterate through that collection of text boxes and retrieve all of the values, including the ones that have just been added after the page was initially rendered. All right, so it's all real time. Let's go ahead—I'm going to hop out of Visual Web Developer and then restart it and create a new website. So the first thing we're going to do is just do the markup. All of the real details are in the code behinds. To begin with I'm going to take this div and at the top of the page— and we're just going to add a style to that, and of course in your production app you're going to want to put styles in a .CSS file and include them, but for the sake of the demo I just want to center align this. So we'll say text-align: center, and then inside this div I'm going to create another div just that we can use as a container with some coloring. I'm going to say style, and we'll set the background color equal to aqua, and we'll set the width equal to—let's just call it 250 pixels just for a little formatting. Then of course let's close our div and now we're ready to go. Because of my limited screen real estate here I'm going to move all those out from a formatting perspective. Now this is going to be an AJAX application of course so the first thing that I need to do is at the top of my form I'm going to add a script manager. So I'll go down to my AJAX extensions tool tab box. Let's change the name here. Now here inside my div the first thing that I'm going to do is just give myself a little bit of space, and then inside the div I'm going to add an update panel. Let's go ahead and grab an update panel, drop it on the page and of course inside my update panel I'm going to need a content template, so let's do that. And inside the content template I'm going to add a placeholder. The reason we need a placeholder here is that the placeholder is going to be the reference item that we're going to program against from our code behind. So really all the magic of this dynamic control mechanism is handled in our code behinds, so in our case it will be Visual Basic or in your case it might be C#. So we need this placeholder to both run at server and we need it to have an identifiable name—so let's just call this "myPlaceHolder" And that's all we need for that. This is where those text boxes will appear. The other thing that we need here is we need to know when to update that update panel, so we're going to add a triggers collection. Now we haven't added any controls that are triggerable yet so let's go ahead and do that. I'm just going to add a little bit more spacing here before we add a control just for formatting purposes. Here let's add just a standard button control and I'll call it "btnAddTextBox" and I know you folks that aren't used to this Hungarian notation— this is just because I'm an old guy and I can't break the habit. So it's not, strictly speaking, necessary in today's modern programming languages, but it comforts me. The next thing that we're going to do here is change the text to say "Add TextBox" and because we're going to program against it let's go ahead and hop over into design mode and double click on that text box so we wire up an event handler that we'll program momentarily. And go back into source mode here. Now we can add that aSynchPostBackTrigger where we'll say that the control ID that we're interested in programming is— well the event is going to be the click event and the ID that we want to be listening to for a click event will be "btnAddTextBox." Okay? So there's the first half our UI. Now we still need the—we still need to get the bit of logic where we— where we retrieve the values from that collection, so let's do that. Actually, let's grab these breaks, put them outside the div— and just add one inside the div—just doing a little bit of formatting here. Now I can add the second update panel since we want this whole application to be AJAX-y, if you will. Here inside the second update panel, again, we need a content template, and inside the content template we're just going to want a couple of things. We're going to want a button and a label, so I'm going to add the spacing that we want just for pretty formatting and then let's go ahead and add a button control and a label control. Let me just call this "MyButton." This is going to get the values. The label will be where we will display the values so we're not going to start with any text value at all. Let's go into design mode and—okay, so this looks like what we want. Let's double click on get values so we generate code behind for that as well, and now we can get to the tricky part. Now the issue here is that the number of controls—or in this case text box controls—that are going to appear on the page are dynamic. That means that they're not statically defined So when the page lifecycle happens we need to be able to determine at the time the page the page is being built how many controls of this particular type—in our case, text box— need to be put on the page because they're not statically defined. The first thing that we're going to need is a variable to hold the number of controls that are going to be added to the page, since every time there's a page post back the lifecycle for this page is going to execute, and we need to figure out for each iterance of the page lifecycle how many controls need to be rendered. So let's add a shared variable so it will keep its value in between post backs. We'll call it MyCount As Integer and let's just give it a default value of five, which means that we want to begin by displaying five text boxes on the page. We're also going to need an array of text boxes so let's—spell dynamic right. Let's create an array of text box items that we'll call dynamicTextBoxes and this is where we will keep them. The next thing that we're going to need is a couple of page events so we need to execute a little bit of logic before the page starts to render. Let's look at page events and we're going to need a page PreInit event. I'm just going to move this to the top of the page since we're going to program it first. And we're also going to need an—we're going to have to override the OnInit, so let's find for page events Init—oh, sorry, that's not what I want to do. Let's go ahead and just code it here. Let's say Protected Overrides OnInit, and we're going to need one more function where—that we can use to actually execute some logic to really do the meat of determining what actually caused the page post back, so let's say Public Shared Function GetPostBackControl. We're going to take the page as an argument so— Okay, so let's see. How do I want to dissect this? Well the first thing that we'll do is let's go up and— Okay, so here is how I'll dissect this. One of the things that we need to do is to figure out what caused the post back. Right? So we need to know whether the thing that caused the page lifecycle to be executing was that someone clicked on our add text box button. To do that let's say Dim myControl As Control and let's set it equal to nothing to get started. All right. And then let's say Dim ctrlName As String = thePage.Request.Params.Get and what we want to look for is ("_EVENTTARGET"). Now eventTarget—let's go back and run that existing application one more time. So let's run this—this is the finished version— because this is another little bit of complexity so let's say view source. What you'll see here is there's this hidden field called eventTarget and the script manager will populate this with whatever caused the post back to happen. However, because of the way that HTML works, this only works for certain controls. It doesn't work for buttons and the reason is that to HTML a button whose action is submit—you can have multiple ones on the page, but it's a different—it's recognized a little bit differently in the way that HTML works. Buttons whose input type is submit—you can have multiple ones on the page, but only the one that causes the post back gets added to the request collection. So in our case, because we're only interested in processing post backs that are caused by the click event of our button control, we're not going to do anything if the—if there is—with the event target. But we want this routine to be reusable so we—in this demonstration we're particularly going against the—a button control being clicked, but you could do the same thing by saying—you know, handling an add check— a check box being clicked for example, and if you were doing it— if you were processing against a check box being clicked then you would be very interested in what the eventTarget said because the eventTarget would detect that click box. All right, so let's go back to our work in progress here. Now we're going to say If ((ctrlName IsNot Nothing— meaning there as something in the control name—And (ctrlName < > String.Empty Then myControl = thePage.FindControl (ctrlName ). All right. Understand what's happening here. In so much as we've programmed so far, we are finding that we're getting this hidden field variable that contains the name of the control that caused the post back, and then we're just doing a little check to make sure that it's in fact valid, and because the eventTarget—the hidden form field eventTarget contained the control name now that—now we know what control caused the post back and we're actually going to go get a reference to the control. However, remember that doesn't work for buttons because of the way that HTML works, so in this case we have to get a little bit more tricky and say For Each Item As String In thePage.Request.Form— so we're going to iterate through all of the form objects that are contained in the request, and so it would say Dim C As Control = thePage.FindControl for whatever the current item is. All right, so we're saying for every item in the forms collection get a reference to the item and now we can say If (TypeOf (c) Is System.Web.UI.WebControls.Button) Then myControl = c. Perhaps just a little bit of explanation—oh yeah, we need to return to value here. Just another—one more pass. I want to make sure everybody understands this. If it's one of the controls that gets—that the script manager stores its name in the eventTarget form field variable, which is hidden, then we look for that, and if we find one then that's the control that caused the post back, but remember that doesn't work for buttons. You can have multiple buttons whose type is submit on the page, but only the one that got clicked that caused the post back will appear in the forms object collection. So what we're going to do is, since the thing that caused the post back wasn't in the eventTarget field, we're going to go through all of the objects in the forms collection, and we're going to find whichever one is a button. Now remember, only the button that causes the post back will appear in this collection. Now that we have a reference to the thing that caused the post back whether it's a regular control or a special button control, now we can go and in our page handling logic, which in our case actually we don't want to be PageInit—we want it to be PreInit. We want this to happen before Init happens so let's add the PreInit function. I'm going to put that at the top of the page since that's where we're working logically. Okay, now here in our PreInit function we can say Dim myControl As Control = GetPostBackControl, which is the—this function that we just implemented— GetPostBackControl, and we pass in the page. All right, so we're just passing in a reference to the page. Now that returns the control that caused the post back, which gets stored in myControl. So now we can say If myControl IsNot Nothing then let's find out If myControl ClientID.ToString ( ) is equal to what we named our add text buttons. So it's "btnAddTextBox." Okay? So, again, what we did here was we called the function we just defined back here found out what the control that caused the post back was, and if it's the add text box button that means that the user wants to add another text box so we can simply take myCount and make it equal to myCount + 1. So the logic we've written so far determines whether or not the user has clicked on the add text box button and added one to the number of text boxes that need to be rendered if, in fact, that's the case. And understand that we need to do that in the PreInit event handler because it's in OnInit where we're actually going to create the text boxes that end up on the page. After calling the base OnInit function, let's say dynamicTextBoxes = New TextBox (myCount - 1) just to get them numbering correctly. Then I can say Dim i As Integer For i =0 to myCount - 1 Step i + 1 All right, and this is—what we're setting up here is an iterator to walk through for however many text box controls we need to add to the page and add them. So we'll say Dim textbox As TextBox = New TextBox ( )—create a new TextBox item. We've got to set the ID, and the IDs have to be unique, so let's set it to— we're going to set those to "MyTextBox" but I can't use the same name for every control— obviously there will be collisions, so in our case—you can be as fancy as you want here. In our case we're just going to say let's append the integer value of our iterator to the name so it will always be unique. All right, so now we've created the text box object. We've set it's ID. Now we need to stick it into the placeholder Let's say myPlaceHolder.Controls—we're going to access the collection, and we're going to call that Add method of that collection and then we're simply going to pop in the text box that we just created. Now it's in the pages controls collection; however, we want to make sure that this new text box that we've just added gets recreated every time the page gets refreshed and that's where this dynamicTextBoxes array fits in. So we're going to say For the i instance let's also add our textBox. And then, because we want each one of these added controls to appear on a line by itself let's say Dim literalBreak, which is our variable name, As LiteralControl = New LiteralControl and this is just going to be a break so we're going to just add some literal text, which will be the HTML for break control, and then of course we have to insert that into the controls collection as well so let's say myPlaceHolder.Controls.Add(literalBreak). Remember this is—this OnInit method is where the number of text boxes actually gets created. So we're starting with five, and then for each one that gets added there will be another iterance in this for loop that takes place. The next thing that we need to do is handle our button click events. For our add text button we don't have to do anything because we want—we need to wire up the event handler. The event handler is not going to actually do anything but we need to wire up the event handler so we get the page post back, but actually all the logic is handled in the PreInit method. Now here for our button click let's just set myLabel.Text = Nothing and now let's iterate through them—them being the text boxes. So let's say Dim tb as TextBox and then For Each tb In dynamicTextBoxes— so this is our array of text boxes that we're maintaining— Let's just say MyLabel.Text += the name of the text box and then resolving to the actual text value and then we'll just put some delimiter. I'll put a couple of colons there and there we go. All right? This last little bit is when we're going to retrieve the values. We're going to start by setting the value in the label equal to an empty string, and then we're going to iterate through all of the text boxes that are on the page, and we know they're on the page because they're kept in this dynamicTextBoxes array, which we've defined here and added to for each new one that the user has added. We're just going to walk through all of those, grab the text that's contained therein, and append a delimiter. That' all we're going to do. Now, just to make sure that we haven't made any mistakes let's go ahead and run it. Remember what's happening in the background. We said start with a value of five. We've hit our PreInit method. We call up GetPostBackControl. GetPostBackControl is going to look and see if there's a value in this hidden field. There won't be. Then it's going to look for a button control in the forms collection. There won't be because this is the first rendering of the page so myControl will be equal to nothing. Things will—so this PreInit for the first loading of the page will exit with nothing actually executing, and then we'll hop into page—to OnInit, where we'll create the array of TextBoxes. We're going to populate for five, so this is setting up the array, which will be the container for all the controls. Then we're going to iterate through that array and populate the page which each of the text box controls. Let's go ahead and put some values in here so when we retrieve them we can see them. All right, now add a text box. So remember what's happening in the background here is that when we hit that controls detection logic in this case we'll actually find a button control in the collection and we're going to return a reference to that control back to our PreInit, which will confirm that that button is the AddTextBox button so it will add one to the count and when we go into OnInit we'll create six text boxes instead of five. And again, if we go ahead and grab the values we get 1, 2, 3, 4, 5 because we didn't add anything in the sixth box. Add something in the sixth box and it will appear. So that's it. Hopefully that will—this video will serve to show you the sort of ins and outs of getting around the natural limitation of the forms-driven design time model of dragging and dropping controls onto your page in a way that lets you dynamically add controls, remembering to use the PreInit and OnInit methods to determine what needs to be rendered on your page. [Microsoft] [ ]

Video Details

Duration: 31 minutes and 4 seconds
Country: United States
Language: English
License: All rights reserved
Genre: None
Views: 6
Posted by: neudesicasp on Sep 5, 2013

In this video I will demonstrate a technique to dynamically add an indeterminate number of controls to your web page.

Caption and Translate

    Sign In/Register for Dotsub to translate this video.