ASP.NET dynamic controls count (creating controls as you go)(ASP.NET 动态控件计数(随时创建控件))

本文介绍了ASP.NET 动态控件计数(随时创建控件)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个复合 ASP.NET 控件,让您可以构建一个可编辑的控件集合.

I'm trying to create a composite ASP.NET control that let's you build an editable control collection.

我的问题是,当我按下添加或回发按钮(除了回发表单之外什么都不做)时,在文本框中输入的任何值都会丢失.

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.

当控件数量在回发之间发生变化时,我无法让它工作.我需要基本上能够在控件生命周期中的两个不同时间重新创建控件树,具体取决于视图状态属性 ControlCount.

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.

此测试可用于重现问题:

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();
    }
}

推荐答案

如果你想玩 ASP.NET 的自定义控件,你必须按照它的规则和挑剔来玩!当您开始在自定义控件中使用 OnPreRender 时,您知道 90% 的时间都在错误的轨道上.

If you want to play with ASP.NET's custom controls, you have to play by its rule and its picky! When you start to play with the OnPreRender in a custom control, you know you're on the wrong track 90% of the time.

通常,使用 ViewState 的最佳方法是声明一个由它支持的属性,就像标准的 ASP.NET 控件所做的一样(.NET Reflector 多年来一直是我的老师!).这样,它会在事件的生命周期中自然地被读取和保存.

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!). 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;
    }
}

这篇关于ASP.NET 动态控件计数(随时创建控件)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!