Вопрос

Ok, I've already learned that in order to keep the dynamic (created) controls and their viewstate in asp.net we must (re)create them in the Page init event, so they already exist within the page's control hierarchy before the view state is loaded.

As it says in this article.

There is no problem to achieve this behaviour if the criteria to create these controls is outside the web environment, for example a database. But what should I do if what I use to decide how many dynamic controls I have to create is actually a value that is in the controls?

I try to explain it with an example, maybe it's clearer:

Let's say that we have a textbox and two buttons. In the textbox I write the number of how many dynamic controls I want to create, for example 4 checkbox. When I hit the button1 the controls should be created. No problem. Then I check some checkboxes and hit the button2 just to fire a postback. Now I should recreate the controls in the page init event, like we said before, in order to maintain the controls and their state.

And here comes the problem. Because of I'm in the init stage I have no viewstate so I'm no able to access the value in the textbox that tells me how many dynamic checkbox should I create.

I thought that storing the value in the session object would do the trick, but it doesn't. The session object is no accessible as well.

Where can I save the value that it'll be accessible from the init event too?

Thanks and sorry for the long post!

Это было полезно?

Решение

First thing - textbox value is not stored/retrieved from view state, you cannot get textbox value from viewstate. Coming to actual problem, here is the sequence of (imp) events init -> load view state -> bind postback data -> page load. You can retrieve textbox value only after bind postback data event (which actually takes posted data and binds to the textbox control). In init only option is to use Request.Form{"textboxid"] to get the textbox value.

Другие советы

You are on the right track.

If you use TextBox, you do not need another ViewState to keep track of how many controls has been created, because TextBox control has its own ViewState already.

You can use either Page_Init or Page_Load to load control back.

enter image description here

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs"
    Inherits="WebApplication2010.WebForm1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:TextBox runat="server" ID="NumberTextBox" />
        <asp:Button runat="server" ID="CreateControlButton" 
            OnClick="CreateControlButton_Click"
            Text="Create Control" />
        <br />
        <asp:PlaceHolder runat="server" ID="PlaceHolder1"></asp:PlaceHolder>
    </div>
    </form>
</body>
</html>

using System;
using System.Web.UI;

namespace WebApplication2010
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (IsPostBack)
            {
                int ids;
                if (Int32.TryParse(NumberTextBox.Text, out ids))
                {
                    for (int i = 0; i < ids; i++)
                    {
                        Control ctrl = Page.LoadControl("WebUserControl.ascx");
                        ctrl.ID = i.ToString();
                        PlaceHolder1.Controls.Add(ctrl);
                    }
                }
            }
        }

        protected void CreateControlButton_Click(object sender, EventArgs e)
        {

        }
    }
}

<%@ Control Language="C#" AutoEventWireup="true" 
    CodeBehind="WebUserControl.ascx.cs"
    Inherits="WebApplication2010.WebUserControl" %>
<asp:CheckBox runat="server" ID="CheckBox1" />
<asp:Button runat="server" ID="Button1" OnClick="Button_Click" 
    Text="Post Back" />
<asp:Label runat="server" ID="Label1" />
<br />

using System;

namespace WebApplication2010
{
    public partial class WebUserControl : System.Web.UI.UserControl
    {
        protected void Button_Click(object sender, EventArgs e)
        {
            Label1.Text = " This control was posted back.";
        }
    }
}

This is the common paradox with page lifecycle when you work with code behind. For example, you save the editing customerid in viewstate but controls need to bind on init to be able to read their posted values.

Best real life solution is to do what bound controls do on postback, call explicilately the LoadPostBackData on IPostBackDataHandler interface that all controls implement, after you have created them in Page Load event.

You should create an extension method for Controls and call it when needed: control.DataBind(); control.LoadPostedData(); // extension method

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top