Sunday, April 17, 2011

How can you move ASP.Net controls to different places on the Web form at runtime?

Is there an accepted way to "move" a control.

My client wants to place a certain chunk of markup (representing some visual element) in one of several different places on the page. The locations are different to the point that I can't effect the change on CSS along (by floating it or something).

I considered just putting the control in multiple spots with Visible set to "false," then displaying the one in the place they wanted for that particular page.

However, the code for this control is not trivial -- there's a couple template sections, for instance. Having to dupe this in multiple places would get unwieldy. Also, I don't want to have to work with this control strictly from the code-behind for the same reason.

So, I'd like to put it in one place on the Web form, the move it around based on where I want it. Could I put Placeholders in different spots, have the control in one spot, then remove and add it to the right spot? I suspect this would work.

Does someone have a better idea? Is there a best practice for this?

From stackoverflow
  • Do Web Parts do what you want to do?

    Or, you can change the parent programmatically of your controls to move them into a separate area.

  • You could always put panels in the pre-defined locations and add the control to the specific panel at runtime.. Here's an example adding a label (the label could be replaced with any control).

    Dim lblDisplay As Label = New Label()
    lblDisplay.ID = "myLabel"
    lblDisplay.Text = "Some Text"
    pnlDisplay.Controls.Add(lblDisplay)
    

    As far as...

    "Also, I don't want to have to work with this control strictly from the code-behind for the same reason."

    I think you're going to have to do most of your work in the code behind.

    PS.. a good example of the whole usercontrol setup can be downloaded here.. http://www.asp.net/downloads/starter-kits/time-tracker/

    Deane : I meant that I didn't want to create it from the code-behind. I don't have a problem manipulating it in some form from the code-behind, but I'd like the bulk of it's mark up in the Web form.
    madcolor : I'm suggesting you create a user-control with the markup that has properties you can get/set and load a panel. No good reason to have your markup sitting in the webform that I can see.
  • You can override the Render method and place the controls wherever you want in the html.

    You only need to add controls to the Controls collection that must interact on the server. The rest of your HTML can just be written to the response stream. If you override Render you can create the html anyway you see fit, placing the controls in any order.

    Below is an example of how to write out your html.

    protected override void Render(HtmlTextWriter writer)
    {
      AddAttributesToRender(writer);
      writer.RenderBeginTag(TagKey);
    
      writer.RenderBeginTag(HtmlTextWriterTag.Div);
      _control.RenderControl(writer);
      writer.RenderEndTag();
    
      writer.RenderEndTag();
    }
    
  • I'd recommend using a placeholder control, moving your markup into a separate user control, then loading this at runtime and adding it to the relevant placeholder.

    Eg.

    // Load a user control
    MyControl userCtrl = (MyControl) LoadControl("~/Controls/MyControl.ascx");
    
    // Or create an instance of your control
    SubclassedControl subclassedCtrl = new SubclassedControl();
    
    // Do stuff with controls here
    userCtrl.LoadData();
    subclassedCtrl.Text = "Hello World";
    
    // Check which placeholder to add controls to
    PlaceHolder placeHolder = (foo=="bar") ? placeHolder1 : placeHolder2;
    
    // Add the controls
    placeHolder.Controls.Add(userCtrl);
    placeHolder.Controls.Add(subclassedCtrl);
    

    This will avoid cluttering up your page with unnecessary markup, and loading it at runtime will also avoid unnecessary confusion later, when another developer looks at the code and can't immediately see why a control is in one place in the markup, but renders on a completely different part of the page.

    Deane : How would I do this if the control is a extension of a standard ASP.Net control, so it exists as a .cs file in App_Code? Would I need to "wrap" it in a User Control (a .ascx file)?
    madcolor : Yes, then you can either load it in a placeholder or a panel.. same diff, only the panel spits a div or span tag where the placeholder doesn't.
    Mun : If you're subclassing a standard ASP.NET control, then rather than loading a control, you could create an instance of your control instead, and then add it to the placeholder. I've updated the code sample above to reflect this.
  • An alternative (and one I've seen done many times before) is through javascript and the DOM. Render your control inside a hidden div tag. So you would render your content here:

    <div id='rendercontent' style='display:none'>
      .. control here ..
    </div>
    

    Then, lets say you wanted to move it all here (the span tag is inside because that's what we're going to replace):

    <div id='newlocation1'><span></span></div>
    

    You would define the following javascript:

    <script language="JavaScript">
    function replaceNode(newElementID, targetElementID)
    {
        var targetElement=document.getElementById(targetElementID);
        var newElement=document.getElementById(newElementID);
        targetElement.replaceChild(newElement, targetElement.firstChild);
    }
    </script>
    

    And when you want to move the content to the new location, call:

    <script language="JavaScript">
    replaceNode('rendercontent','newlocation1');
    </script>
    

0 comments:

Post a Comment