I am trying to add controls to the Dialog control dynamically. I add the controls to the ContentPane.TemplateControl.Controls collection. Whenever I do this, the control ends up on the page hosting the dialog and not in the dialog.
Is there something I need to do to get it to show up in the dialog correctly?
-Daniel
The sure fire way to add a control at runtime is to first add a placeholder control at Design-time. If you add the PlaceHolder control in the Dialog box at design-time, you can simply add your control to the PlaceHolder control's .Controls collection.
If your child control is still not showing up in the right place, my guess is that you have a CSS issue - ie. your child control is absolutely positioned, which is making it appear outside of the bounds of its container.
-Tony
Thanks for the response.
The problem is I want to inherit from the Dialog control and add my standard controls to the inherited class. Is this something that can be done with the dialog control? If not then I will just end up creating my own .ascx control which contains the dialog, but I was hoping to inherit from it instead.
Daniel,
Looks like you're adding the control to the wrong controls collection. You'll want to use the ConentPane.Controls collection instead. That's why your control isn't showing up in the content area of the Dialog Window. Also, here's a quick tip for extending one of our controls in this type of scenario- use the CreateChildControls override. I'm not sure if this was what you were already doing, but it's the recommended approach. Here's a quick example:
public class MyDialog : WebDialogWindow{ protected override void CreateChildControls() { base.CreateChildControls(); TextBox tb = new TextBox(); tb.ID = "tb1"; tb.Text = "text"; this.ContentPane.Controls.Add(tb); }}
Thank you, that did what I expected. There is one thing I don't understand though. If I add controls dynamically this way, you can not also add additional controls via the design surface.
Here is an example of what I am talking about. I inerit from the webdialogwindow and add some buttons. Another developer can then drop this new control on the design surface and start adding controls to the markup. The problem is that none of the new controls show up. If I skip over adding the buttons, then the additional controls will show up.
So I can only seem to get one or the other. Is there a way to allow developers to use the new control on the design surface and still add controls dynamically?
Thanks again for you help.
Be sure you're calling base.CreateChildControls as this is responsible for taking the template and instantiating the controls into the WebDialogWindow. Also, be sure not to manually call "CreateChildControls" from your code anywhere. You should instead use EnsureChildControls (unless you're inside of the CreateChildControls method override).
Thanks for the response. I am not doing any of those things you mentioned. My code is very simple:
public class SaveDialog : WebDialogWindow { private TextBox _box;
protected override void CreateChildControls() { base.CreateChildControls();
_box = new TextBox(); _box.ID = "foo"; _box.Text = "yah";
ContentPane.Controls.Add(_box); }
Here is the code in the .ascx
<cc1:SaveDialog ID="SaveDialog1" runat="server"> <ContentPane> <Template> <asp:Button ID="Button1" runat="server" Text="Button" /> </Template> </ContentPane></cc1:SaveDialog>
The button doesn't show up, only the textbox.
Ok, I found the problem. If you look at the source code for the WebDialogWindow, you'll see an EnsureTemplates method. This method checks to see if the ContentTemplate !=null && !ContentPane.HasControls
Since your code above is actually adding controls to the ContentPane, EnsureTemplates will fail this check.
The fix is simple. Instead of adding your controls in CreateChildControls, you should add your controls inside of EnsureTemplates. Just be sure to call base.EnsureTemplates BEFORE you add anything to the ContentPane.Controls. Also, since the EnsureXXX pattern means that the method may be called multiple times, you'll want to wrap your controls.add code in a check to be sure that you haven't already called this method. Here's the code I would use:
public override void EnsureTemplates(){ if(!this.ContentPane.HasControls()){ base.EnsureTemplates(); this.ContentPane.Controls.Add(...); }else base.EnsureTemplates();}
The idea behind the "Ensure" pattern is that it can be called multiple times and only call the "Create" method once. So in this case, EnsureTemplates can be called 100 times, and only call CreateChildControls once. That's the simplified version. In this case though, the code is checking for an explicit condition as well, to be sure that controls haven't already been added to the controls collection. It's sort of a safegaurd against adding the same content multiple times. Unfortunately, this check is what prevents new content from being added through the designer, if you add your own controls manually as you were initially doing. Either way, I suggest you download the source - it will help tremendously in this case, and that's what it's there for.. to help. Let me know if you still can't find a solution for this.
Thanks again for the quick response. I did what you said, and it did not work. :) It looks like EnsureTemplates is called several times before it actually ensures that the templates are there, which seems strange. I added some logic to only add my additional controls once the template controls are there, but this feels hacky since I would expect EnsureTemplates to actually ensure the templates are there. :) I don't have the source code to see what is going on. I will need to download it and set that up to try and figure out what is really going on.
Thanks again for the help though.