Question

I imagine this question has been asked before (hasn't every question?), but I am struggling with the language necessary to find my way to a solution, so here are some specifics:

I have a web form for updating a single location, e.g. street address, city, state, etc., which is dealt with by having a static location-update form with various asp:TextBoxes which are referenced in the code-behind using their intellisensed controls, e.g. StreetAddressTextBox.Text.

I would like to update this form to work for multiple locations. In the past when I worked with PHP, this meant writing a lot of inline code wherein I wrapped the form-contents in a for-loop over the collection I was rendering, and then referenced each item with some ID="StreetAddressTextBox_<%=locationId%>"-like schema.

I'm currently in the process of doing it this way in ASP.NET, but inline feels dirty, especially because I have to kick a lot of code-behind paradigms I've established on other pages where the form-content wasn't scaling based on a collection. My gut tells me there should be some way to template out a location and do everything in the code-behind, but I've yet to stumble upon and example that shows me this in practice.

Thanks for any help in advance.

Was it helpful?

Solution

Assuming I understand you correctly it sounds like you should be using a UserControl.

Basically create a UserControl.ascx file (and VS will generate the UserControl.designer.cs and code-behind classes for you). Then put your input fields in there with no special attributes, like so:

(Note that I prefer HtmlControls to WebControls, they give cleaner markup and don't muddy things. I suggest you give them a try):

<%@ Control blargh %>
<label for="<%= Street.ClientID %>">Street address</label>
<input type="text" runat="server" id="Street" /> <br />

<label for="<%= City.ClientID %>">Town / City</label>
<input type="text" runat="server" id="City" /> <br />

<!-- etc -->

Note how I'm not messing with the id="" attribute of the input controls. Now just register it in your web.config:

<add tagPrefix="foo" tagName="Address" src="~/Controls/Address.ascx" />

Then in each page that needs an address form (assuming your UserControl is called AddressControl)

<%@ Page blargh %>
<p>Enter your address details below:</p>
<foo:Address runat="server" id="Address" />

Then in your page's code-behind you can just do this:

 public override void OnLoad(Object sender, EventArgs e) {
      if( Page.IsPostBack ) {
          Validate();
          if( Page.IsValid ) {
              // get values from a POST
              String street = this.Address.Street.Value;
              String city   = this.Address.City.Value;
              // and so on
          }
      } else {
          // set values if you're retrieving data from a DB or something
          this.Address.Street.Value = "123 Fake Street";
          this.Address.City.Value = "Frying Pan City";
      }
 }

Note how I used the "<%= Street.ClientID %>"-thing. ASP.NET will automatically generate the control names and IDs based on the control's parent name (and so on, recursively). So the actual HTML input will be rendered like this:

<label for="Address.Street">Street address</label>
<input type="text" name="Address_Street" id="Address.Street" />

Note this design and practice only applies to WebForms. ASP.NET MVC is completely different again.

OTHER TIPS

You could just use an <asp:PlaceHolder runat="server" id="plcDynamicControls" />.

In your code behind create a private List<WebControl> dynamicControls.

During .Init() return whatever logic is appropriate for your locationID requirements, and whatever your field requirements might be.

Say locationID = 4 required Name, Address1, Address2 fields:

Page_Init(object Sender, EventArgs e) 
{
    TextBox txt = new TextBox(){
        ID = "txtName"    
    };
    plcDynamicControls.Controls.Add(txt); //Add to Form
    dynamicControls.Add(txt); //Add to reference list, to avoid having to do .FindControl()

    TextBox add1 = new TextBox(){
        ID = "txtAddress1"    
    };
    plcDynamicControls.Controls.Add(add1); 
    dynamicControls.Add(add1); 

    TextBox add2 = new TextBox(){
        ID = "txtAddress2"    
    };
    plcDynamicControls.Controls.Add(add2);
    dynamicControls.Add(add2); 
}

Build a nice loop to add controls like that to your placeholder.

In your .Click() event from your submit button you can iterate through the List<WebControl> dynamicControls collection and process the response.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top