asp.net在回发后动态添加用户控件保存值

时间:2010-10-15 19:11:41

标签: c# asp.net user-controls dynamically-generated

这是我的问题。我有一个usercontrol,我希望允许用户使用按钮单击添加任意数量的实例(每次单击一个按钮,我想将另一个用户控件实例添加到Panel)。它第一次工作正常,但每个额外的回发删除所有添加的控件。我跟踪用户添加的用户控件的数量没有问题,但我如何确保它们保持在回发之前的状态?我已经阅读了一些关于使用SaveViewState和LoadViewState的人的帖子,但我找不到任何例子。

我最大的问题是确保每个用户控件的所有文本框和下拉列表在每次回发后都保持填充相同的文本/选定值/数据

提前致谢, 本

7 个答案:

答案 0 :(得分:10)

由于您是以编程方式向页面添加控件,因此您需要在每次回发时重新创建它们。

此外,您必须在页面的PreInitInit事件上重新创建以编程方式添加的控件。这适用于正确的视图状态恢复事件管理。

如果你不这样做,控制将在回发时消失,他们将不会处理任何事件。

修改

虽然建议在PreInitInit添加动态控件,但如果您在page_load上添加它们,则可能会有效(如Dustin Hodges所说)。我会说你应该避免它,除非你别无选择。

  
    

您可以通过加载控件来逃脱     Page_Load事件处理程序并正确维护视图状态     这一切都取决于你是否以编程方式设置动态加载控件的任何属性,如果是,那么当你相对于     Controls.Add被(dynamicControl)     行。
    对此的深入讨论有点超出了本文的范围,但它可能起作用的原因是因为     Controls属性的Add()方法以递归方式将父视图状态加载到其子视图中,即使已经过了加载视图状态阶段。

  

来源MSDN

答案 1 :(得分:4)

答案 2 :(得分:2)

如果要跟踪用户添加的控件数量,则需要重新创建用户之前添加的控件,最好是在Page_Init或Page_Load中。将这样的内容添加到该处理程序中:

for(int i=0; i<NumberOfControlsUserHasAdded; i++)
{
    //todo:  change this to the appropriate user control
    TextBox tb = new TextBox();
    tb.ID = "tb" + i.ToString();
    //todo:  add to appropriate control collection
    this.Controls.Add(tb);
}

如果以这种方式执行,则应该保持控件的状态,因为当您将tb控件添加到控件集合时,它会捕获事件并自动恢复其视图状态。

您不应该在会话中跟踪他们的状态,因为在大多数情况下,它将存储在视图状态中

答案 3 :(得分:1)

我曾经做过一次噩梦,试图在一个旧项目中解决这个问题。在中间阶段,我发现我对Web开发的了解远远少于我的想法(阅读这个网站是一个很好的方式来谦卑自己每天 - 如果不是每小时 - 基础上)。在那个项目中,Page.IsPostBack对我来说完全没用,因为我已经动态地实例化了控件。

话虽这么说,我建议的最好的事情是考虑使用Session变量。如果你有一个类(或类的集合)代表你从页面捕获的数据,那么也许最容易在该类/集合中存储值以提高代码可读性,然后将其写入会话。

答案 4 :(得分:0)

查看您的PageLoad并在清除面板的行前添加if(!this.IsPostBack)

这当然只是一个猜测,但我已经看到很多问题,这个问题与此有关。

答案 5 :(得分:0)

我认为可能发生的事情是当您点击添加按钮时,Page_Load会触发您创建一个全新的页面。然后,按钮单击方法添加控件,页面完成渲染。当您第二次单击它时,Page_Load会创建您的页面,再次按钮单击方法会创建一个控件并将其添加到页面中。不幸的是,你之前添加的那个不再存在。

如果您将控件添加到Repeater会怎样? Repeater的视图状态可以跟踪您添加的每个控件,以便在回发后,它不会被吹走。

答案 6 :(得分:0)

如果您拥有大量用户,这是一个丑陋的解决方案,但您可以将用户控件自己粘贴到会话中。 我使用页脚控件执行此操作,因为每次页面更改以重新创建页脚时,我都不想访问数据库。

如果您拥有大量用户并且他们经常使用此功能,则此解决方案可以在服务器上获得真正的任务。至少我认为它会...

但是您可以在page_load上重新填充其中包含usercontrols的占位符。我可以很快提出一个例子。

我做的例子:

if (Session["footer"] == null)
{
 Session["footer"] = new Footer(LinksRules.BuildFooterLinks((int)WebSiteSections.Main));// where Footer is my control
}
footerPH.Controls.Add((Footer)Session["footer"]);

像单身模式一样......

因此,我认为你可以在任何导致回发的事情上做到这一点

Session [“DynamicControls”] = PlaceHolder.Controls;

并且在页面加载方法中你可以:

foreach(var control in (List<Controls>)Session["DynamicControls"])
{
  yourPlaceHolder.Controls.Add(control);
}

如果会话对象为null,只需添加一个就像他们从未去过那里的那个......

我相信这会依赖于您想要的控件内的数据。