7

这是我的问题。我有一个用户控件,我希望允许用户使用按钮单击添加尽可能多的实例(每次单击按钮时,我想将我的用户控件的另一个实例添加到面板)。它第一次运行良好,但每次额外的回帖都会删除所有添加的控件。我可以毫无问题地跟踪用户添加的用户控件的数量,但是我如何确保它们保持在回发之前的相同状态?我已经阅读了一些关于人们使用 SaveViewState 和 LoadViewState 的帖子,但我找不到任何示例。

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

在此先感谢,本

4

7 回答 7

10

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

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

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

编辑

尽管PreInit建议Initpage_load. 我会说你应该避免它,除非你别无选择。

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

来源MSDN

于 2010-10-15T19:21:29.150 回答
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 控件添加到控件集合时,它会赶上事件并且应该自动恢复它的视图状态。

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

于 2010-10-15T19:24:29.917 回答
1

我有一段时间试图在一个旧项目上实现这一目标的噩梦。在中间的时间里,我发现我对 Web 开发的了解比我想象的要少得多(阅读这个网站是每天(如果不是每小时)谦卑自己的好方法)。在那个项目中,Page.IsPostBack 对我来说完全没用,因为我已经动态地实例化了控件。

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

于 2010-10-15T19:19:54.457 回答
0

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

如果您有很多用户并且他们经常使用此功能,则此解决方案可以真正在服务器上执行任务。至少我认为会...

但是您可以在 page_load 上重新填充包含用户控件的占位符。我可以很快举一个例子。

我做的例子:

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;

在 page-Load 方法中,您可以:

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

如果会话对象为空,只需添加一个他们从未去过的对象..

我相信这会像您想要的那样保留在控件内的数据上。

于 2010-10-15T19:25:21.887 回答
0

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

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

于 2010-10-15T19:16:46.893 回答
0

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

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

于 2010-10-15T19:17:36.547 回答