简体   繁体   English

ASP.NET动态控件计数(随时创建控件)

[英]ASP.NET dynamic controls count (creating controls as you go)

I'm trying to create a composite ASP.NET control that let's you build an editable control collection. 我正在尝试创建一个复合ASP.NET控件,让您构建一个可编辑的控件集合。

My problem is that when I press the add or postback button (which does nothing other than to postback the form) any values entered in the text boxes are lost. 我的问题是,当我按下添加或回发按钮(除了回发表单之外什么都没做)时,在文本框中输入的任何值都将丢失。

I can't get it to work when the number of controls change between postbacks. 当回发之间的控件数量发生变化时,我无法使其工作。 I need to basically be able to recreate the control tree at two different times in the control life-cycle depending on the view state property ControlCount . 我需要基本上能够在控制生命周期中的两个不同时间重新创建控制树,具体取决于视图状态属性ControlCount

This test can be used to reproduce the issue: 此测试可用于重现该问题:

public class AddManyControl : CompositeControl
{
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        EnsureChildControls();
    }

    protected override void CreateChildControls()
    {
        var count = ViewState["ControlCount"] as int? ?? 0;

        for (int i = 0; i < count; i++)
        {
            var div = new HtmlGenericControl("div");
            var textBox = new TextBox();
            textBox.ID = "tb" + i;
            div.Controls.Add(textBox);
            Controls.Add(div);
        }

        ViewState["ControlCount"] = count;

        var btnAdd = new Button();
        btnAdd.ID = "Add";
        btnAdd.Text = "Add text box";
        btnAdd.Click += new EventHandler(btnAdd_Click);
        Controls.Add(btnAdd);

        var btnPostBack = new Button();
        btnPostBack.ID = "PostBack";
        btnPostBack.Text = "Do PostBack";
        Controls.Add(btnPostBack);
    }

    void btnAdd_Click(object sender, EventArgs e)
    {
        ViewState["ControlCount"] = (int)ViewState["ControlCount"] + 1;
    }

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);
        // If I remove this RecreateChildControls call
        // the collection lags behind each postback
        // because the count is incremented in the btnAdd_Click event handler
        // however, the values are not lost between postbacks
        RecreateChildControls();
    }
}

If you want to play with ASP.NET's custom controls, you have to play by its rule and its picky! 如果你想使用ASP.NET的自定义控件,你必须遵循它的规则和挑剔! When you start to play with the OnPreRender in a custom control, you know you're on the wrong track 90% of the time. 当您开始在自定义控件中使用OnPreRender时,您知道90%的时间都在错误的轨道上。

Generally, the best way to use the ViewState is to declare a property backed up by it, just like the standard ASP.NET controls do (.NET Reflector has been my teacher for years!). 通常,使用ViewState的最佳方式是声明由它备份的属性,就像标准的ASP.NET控件一样(.NET Reflector已经成为我的老师多年了!)。 This way, it will be read and saved naturally during the event's lifecycle. 这样,它将在事件的生命周期中自然地被读取和保存。

Here is a code that seems to do what you want, quite naturally, without any trick: 这是一个代码似乎做你想要的,非常自然,没有任何技巧:

public class AddManyControl : CompositeControl
{
    private void AddControl(int index)
    {
        var div = new HtmlGenericControl("div");
        var textBox = new TextBox();
        textBox.ID = "tb" + index;
        div.Controls.Add(textBox);
        Controls.AddAt(index, div);
    }

    protected override void CreateChildControls()
    {
        for (int i = 0; i < ControlsCount; i++)
        {
            AddControl(i);
        }

        var btnAdd = new Button();
        btnAdd.ID = "Add";
        btnAdd.Text = "Add text box";
        btnAdd.Click += new EventHandler(btnAdd_Click);
        Controls.Add(btnAdd);

        var btnPostBack = new Button();
        btnPostBack.ID = "PostBack";
        btnPostBack.Text = "Do PostBack";
        Controls.Add(btnPostBack);
    }

    private int ControlsCount
    {
        get
        {
            object o = ViewState["ControlCount"];
            if (o != null)
                return (int)o;

            return 0;
        }
        set
        {
            ViewState["ControlCount"] = value;
        }
    }

    void btnAdd_Click(object sender, EventArgs e)
    {
        int count = ControlsCount;
        AddControl(count);
        ControlsCount = count + 1;
    }
}

我相信你必须将控件添加到视图状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM