views:

1195

answers:

5

In one of my projects I need to build an ASP.NET page and some of the controls need to be created dynamically. These controls are added to the page by the code-behind class and they have some event-handlers added to them. Upon the PostBacks these event-handlers have a lot to do with what controls are then shown on the page. To cut the story short, this doesn't work for me and I don't seem to be able to figure this out.

So, as my project is quite involved, I decided to create a short example that doesn't work either but if you can tweak it so that it works, that would be great and I would then be able to apply your solution to my original problem.

The following example should dynamically create three buttons on a panel. When one of the buttons is pressed all of the buttons should be dynamically re-created except for the button that was pressed. In other words, just hide the button that the user presses and show the other two.

For your solution to be helpful you can't statically create the buttons and then use the Visible property (or drastically change the example in other ways) - you have to re-create all the button controls dynamically upon every PostBack (not necessarily in the event-handler though). This is not a trick-question - I really don't know how to do this. Thank you very much for your effort. Here is my short example:

From the Default.aspx file:

<body>
    <form id="form1" runat="server">
    <div>
        <asp:Panel ID="ButtonsPanel" runat="server"></asp:Panel>
    </div>
    </form>
</body>

From the Default.aspx.cs code-behind file:

using System;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace DynamicControls
{
    public partial class _Default : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            AddButtons();
        }

        protected void AddButtons()
        {
            var lastClick = (string) Session["ClickedButton"] ?? "";

            ButtonsPanel.Controls.Clear();
            if (!lastClick.Equals("1")) AddButtonControl("1");
            if (!lastClick.Equals("2")) AddButtonControl("2");
            if (!lastClick.Equals("3")) AddButtonControl("3");
        }

        protected void AddButtonControl(String id)
        {
            var button = new Button {Text = id};
            button.Click += button_Click;
            ButtonsPanel.Controls.Add(button);
        }

        private void button_Click(object sender, EventArgs e)
        {
            Session["ClickedButton"] = ((Button) sender).Text;
            AddButtons();
        }
    }
}

My example shows the three buttons and when I click one of the buttons, the pressed button gets hidden. Seems to work; but after this first click, I have to click each button TWICE for it to get hidden. !?

+1  A: 

One thing I notice is that when you click a button you are invoking AddButtons() twice, once in the Page_Load() and once in the button_Click() method. You should probably wrap the one in Page_Load() in an if (!IsPostBack) block.

if (!IsPostBack)
{
   AddButtons();
}
tvanfosson
Dynamically added controls need to be created every request. But you are right in that you don't need to create them twice.
Slace
The AddButtons in Page_Load is there to recreate the controls of the page so that the event-handling process of the page can commence. The AddButtons in button_Click is there to remove the original controls created in Page_Load and add the new buttons, now hiding the button that was clicked.
Alfred B. Thordarson
A: 

AFAIK, creating of controls should not be placed in Page_Load but in Page_PreInit (ViewState and SessionState is loaded before Page_Load but after Page_PreInit).

With your problem, I would suggest to debug the AddButtons function to find out what exactly (and when) is stored in Session["ClickedButton"]. Then, you should be able to figure out the problem.

gius
You are right, recreating the controls so that event-handling can commence should be in OnPreInit - however moving it in there does not solve my problem. Also there does not seem to be any problems in my "Session-logic". My problem is that my buttons keep getting new IDs when they are recreated.
Alfred B. Thordarson
+2  A: 

I think that you have to provide the same ID for your buttons every time you add them like this for example (in first line of AddButtonControl method):

var button = new Button { Text = id , ID = id };


EDIT - My solution without using session:

public partial class _Default : Page
{
    protected override void OnPreInit(EventArgs e)
    {
        base.OnPreInit(e);
        AddButtons();
    }

    protected void AddButtons()
    {
        AddButtonControl("btn1", "1");
        AddButtonControl("btn2", "2");
        AddButtonControl("btn3", "3");
    }

    protected void AddButtonControl(string id, string text)
    {
        var button = new Button { Text = text, ID = id };
        button.Click += button_Click;
        ButtonsPanel.Controls.Add(button);
    }

    private void button_Click(object sender, EventArgs e)
    {
        foreach (Control control in ButtonsPanel.Controls)
            control.Visible = !control.Equals(sender);
    }
}
Panos
You are right, when I change my code as you suggest, adding "ID = id" my problem is solved - thank you very much. However, in your code you are cheating :-) because I specifically asked for Visible not being used, but only dynamically adding the buttons that should be visible. :-) But thanks again.
Alfred B. Thordarson
+2  A: 

You need to make sure that your dynamic controls are being added during the Pre_Init event.

See here for the ASP.NET Page Lifecycle: http://msdn.microsoft.com/en-us/library/ms178472.aspx

When adding events you need to do it no later than the Page_Load method and they need to be added every single request, ie you should never wrap event assignment in a !IsPostBack.

You need to create dynamic controls ever single request as well. ViewState will not handle the recreation on your behalf.

Slace
You are right, recreating the controls so that event-handling can commence should be in OnPreInit - however moving it in there does not solve my problem. My problem is that my buttons keep getting new IDs when they are recreated.
Alfred B. Thordarson
A: 

the controls that are added dynamically are not cached so this migth me one of your problems

Oscar Cabrero
I don't understand your answer!?
Alfred B. Thordarson