动态访问创建的控件(C#)

4
在我的c#代码后端中,我动态创建了一些RadioButtonLists,并在每个列表中添加了更多的RadioButtons。我将所有控件放置到一个特定的Panel中。 我需要知道的是如何在稍后访问这些控件,因为它们不是在.aspx文件中创建的(无法使用工具箱中的拖放功能)?
我尝试了以下方法:
    foreach (Control child in panel.Controls)
    {
        Response.Write("test1");
        if (child.GetType().ToString().Equals("System.Web.UI.WebControls.RadioButtonList"))
        {
            RadioButtonList r = (RadioButtonList)child;
            Response.Write("test2");
        }   
    }

我的页面上没有显示“test1”和“test2”。这意味着这个逻辑有问题。您有什么建议吗?


2
你可以用多种更好的方式重写循环,其中一种是 foreach (RadioButtonList list in panel.Controls.OfType<RadioButtonList>())。只是提供一个FYI。但使用 child.GetType().ToString()... 将是我想到的最后一种方法。例如,一个 if 可能会说 if (child is RadioButtonList) - Anthony Pegram
同意前面的评论,而且...你确实需要掌握一些 C# 的知识,比如 "is" 关键字... - flq
感谢您的建议。虽然我的代码没有问题,但这更有意义。 - Aliens
3个回答

2

每次 postback 后,您必须重新创建控件。

ASP.NET 是无状态的,也就是说,当您将页面 postback 到服务器时,您动态创建的控件将不再是页面的一部分。

上周我又遇到了这种情况。

我做了什么? 我将用于创建控件的数据保存在 Session 对象中。在 PageLoad 方法中,我传递相同的数据以重新创建动态控件。

我的建议是: 编写一个创建动态控件的方法。

在 PageLoad 方法中检查是否为 postback...

if(Page.IsPostBack)
{
   // Recreate your controls here.
}

一个非常重要的事情:为您动态创建的控件分配唯一的ID,这样ASP.NET就可以重新创建这些控件并绑定它们现有的事件处理程序,还原它们的ViewState等。
myControl.ID = "myId";

我曾经花费很多时间学习这个东西的工作原理。一旦你掌握了它,你就有了强大的能力。动态创建的控件为你打开了新的可能性。

正如Frank所提到的:你可以使用"is"关键字来简化生活...

if(child is RadioButtonList)


注意: 值得一提的是,有关ASP.NET页面生命周期概述的更多参考信息,请参阅MSDN上的ASP.NET页面生命周期概述页面。


好的,我会听从您的建议。 - Aliens
告诉我一些东西。 如果我将文本框保存到会话中(我需要将每个文本框单独保存到不同的会话中吗?),那么如何在下一页获取该文本框中的文本(因为我保存了没有用户编写文本的文本框对象到会话中)?我以文本框为例,但类似于单选按钮。 - Aliens
看,有两种情况。假设我创建了3个文本框。第一种情况:我在代码中分配文本框.Text属性,如下所示: textbox1.Text = "first text"; textbox2.Text = "second text"; textbox3.Text = "third text";第二种情况:我不在代码中分配文本框.Text属性,因为我想从用户那里获取文本。当用户单击提交时,他的文本不会保存在textbox.Text属性中(它们为空)。我想当用户输入文本时,文本必须保存在该属性中。但我不知道该怎么做。 - Aliens
@Aliens:抱歉没有及时回复。你所描述的应该由ASP.NET ViewState处理。每个文本框都有一个名为EnableViewState的属性。在创建动态控件时,将此属性分配为true。当控件在每次postback后重新创建时,它应该重新显示用户输入的值。使其成为可能的是TextBox ID属性。ASP.NET知道在提交回来之前页面上有一个带有该ID的TextBox。因此,现在它知道应该为正在重新创建的相同TextBox获取相同的值(匹配ID)。 - Leniel Maccaferri
你好,感谢您的回复。无论如何,我使用cookie解决了我的问题。我使用JavaScript将文本框和单选按钮列表中的值保存到cookie中。在postback之后,我重新获取这些值。我不确定这是否是最佳解决方案,但至少它可以工作。 - Aliens
显示剩余4条评论

1

0

我认为在PageLoad中创建控件并不是正确的做法,首先ASP.NET的生命周期是从初始化开始;加载ViewState数据;加载PostData;对象加载等等。

如果你在Page_Load中创建控件,你将会失去ViewState、事件等等。

正确的做法是在PageInit中进行,或者如果是控件则在OnInit中进行。

接下来的难点是,在PageInit中你没有可用的ViewState,如果你需要重建一些对象的数量,你需要在一个隐藏域中存储一些上下文/信息,然后在PageInit中检索这些信息,创建对象,完成!

例如:

假设你需要创建1..N个文本框,你可以创建一个HTML隐藏域(不带runat=server),比如NumberOfTextBoxes。

当你执行PageInit代码时:你检索值,例如numberOfTextBoxes = Request.Form["NumberOfTextBoxes"],然后创建文本框。

记住最重要的是匹配存在ViewState中的控件的数量和顺序。


我对文本框的数量和它们的ID没有问题。 但是我无法从文本框中获取文本(请查看Leniel Macaferi答案中的评论)。如果您有任何解决方案,我将不胜感激。 - Aliens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接