Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.NET动态控件计数(边创建控件边运行)_C#_Asp.net_Webforms - Fatal编程技术网

C# ASP.NET动态控件计数(边创建控件边运行)

C# ASP.NET动态控件计数(边创建控件边运行),c#,asp.net,webforms,C#,Asp.net,Webforms,我正在尝试创建一个复合ASP.NET控件,让您可以构建一个可编辑控件集合 我的问题是,当我按下add或postback按钮(除了回发表单外,它什么也不做)时,文本框中输入的任何值都会丢失 当回发之间的控件数量发生变化时,我无法让它工作。根据视图状态属性ControlCount,我基本上需要能够在控件生命周期的两个不同时间重新创建控件树 此测试可用于重现问题: public class AddManyControl : CompositeControl { protected overri

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

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

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

此测试可用于重现问题:

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();
    }
}
公共类AddManyControl:CompositeControl
{
受保护的覆盖无效加载(事件参数e)
{
基础荷载(e);
ensureChildControl();
}
受保护的覆盖无效CreateChildControls()
{
变量计数=视图状态[“控制计数”]为int???0;
for(int i=0;i
我认为必须将控件添加到视图状态

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

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

下面是一段代码,它似乎可以做你想做的事情,非常自然,没有任何技巧:

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;
    }
}
公共类AddManyControl:CompositeControl
{
私有void AddControl(int索引)
{
var div=新的HtmlGenericControl(“div”);
var textBox=新的textBox();
textBox.ID=“tb”+索引;
div.Controls.Add(文本框);
控件。AddAt(索引,div);
}
受保护的覆盖无效CreateChildControls()
{
for(int i=0;i
不,它不是那样工作的。这是另外一回事。某些生命周期事件不会第二次运行(因为正在重新创建控制树)。由于每次回发时都会从头开始重新添加所有
文本框
,因此它们如何恢复其文本值?asp.net做了什么吗?这是非常微妙的,这是肯定的。但您的意思是,我所要做的就是避免在预渲染期间重新创建控件集合,如果我在事件完成处理后再创建控件集合,那就没问题了?我现在通过远离on PreRender事件使它工作了,我也不能期望能够重新创建控件并保持视图状态。真是太遗憾了。我必须在该事件期间仅添加新控件才能使其工作。我只是想重新创建控件集合,并希望它能工作。但它不。。。