65.9K
CodeProject 正在变化。 阅读更多。
Home

动态控件、页面生命周期、MultiView 和 Wizard

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.67/5 (2投票s)

2007 年 2 月 20 日

7分钟阅读

viewsIcon

70472

在 ASP.NET 中,关于在 MultiView 和 Wizard 中使用动态控件编写用户控件的最佳实践

引言

在我看来,页面生命周期没有被充分理解,并且通过适当的编码,
我们可以摆脱大部分问题。

在本篇文章中,我涵盖了三个主题:

  • 在哪里创建动态控件,当动态控件在 DataBound 中创建时
    控件
  • 如何处理 MultiView 中所有控件的 Page_Load 都会被调用
    而不管视图是否活动。
  • 编写可以驻留在 MultiView 中的用户控件的最佳实践是什么?
  • 我已触及页面生命周期与动态控件创建的关系。

通常,我们会在控件的 **Page_Load** 中添加代码。只要
我们知道该控件将始终是页面的直接子控件,我们就可以这样做,但这可能
不总是如此(例如,您在 MultiView 或 Wizard 中有一个用户控件)。在 Page_load 中调用
初始化逻辑会造成性能损耗,因为即使视图不显示,MutiView 中所有视图的 Page_load
都会被调用。在 Page_load 中进行数据绑定是没有意义的。在 MultiView 和 Wizard 中,Page.ISPostBack 始终为 true
即使这是视图第一次可见。所以您需要自定义逻辑来确定它是否是
postback。请阅读第 (4) 项,了解如何在视图可见时确定实际发生的 postback。
是第一次视图将要可见。所以您需要自定义逻辑来确定它是否是
postback。请阅读第 (4) 项,了解如何在视图可见时确定实际发生的 postback。
注:这些建议应该对 **MultiView** 和 **Wizard** 都有效。

我写这些 FAQ 是为了涵盖文章中描述的所有主要要点。

在 MultiView 中的控件初始化的最佳方法是什么?

  1. 在 MultiView 中的控件初始化的最佳方法是什么?

在需要时,在适当的事件(如 ActiveViewIndexChanged 或 Page_Load)中调用 MultiView 中控件的 Initialize 方法。
ActiveViewIndexChanged 或 Page_Load。Initialize 方法可以获取正确的
postback 或数据绑定的参数。当控件没有使用 ObjectDataSource 进行隐式数据绑定时,Initialize 方法可以调用控件的数据绑定(显式数据绑定)。
(显式数据绑定),当控件没有使用 ObjectDataSource 进行隐式数据绑定时。
如果您不知道 ObjectDataSource 是什么,或者什么是隐式数据绑定,
请阅读一些关于 ObjectDataSource 的好书。我将尝试在几句话中介绍它。
在您的用户控件中,假设您有一个 FormView。FormView 有一个名为 DataSourceID 的属性。
属性。该属性用于将控件与
SQLDataSource 或 ObjectDataSource 绑定。使用 SQLDataSource 不是一个好的设计,因为这样您就将 UI 与数据访问层绑定了。使用 ObjectDataSource,您可以将
UI 元素(如 FormView)与业务实体关联起来。业务实体的属性可以绑定
到 UI 元素。

如果您在 ASCX 文件中输入以下代码

asp:ObjectDataSource id=ObjectDataSource1 CacheExpirationPolicy="Sliding" 

CacheDuration="300" TypeName="DataAccess" 

SelectMethod="GetData" runat="server">

<SELECTPARAMETERS>

<asp:Parameter Direction="input" Type="string" Name="p_sortExpression">

</asp:Parameter>

<asp:Parameter Direction="input" Type="string" Name="p_sortDirection">

</asp:Parameter>

</SELECTPARAMETERS>

</asp:ObjectDataSource>

现在,在您的 FormView 的 DataSourceID=ObjectDataSource1 中,数据访问对象(请参阅
上面的 TypeName 属性)将用于隐式绑定 FormView。
每当此用户控件在页面上显示时,都会自动为此控件调用数据绑定。
这称为隐式数据绑定。您也可以在需要时通过调用
FormView.DataBind() 来进行显式数据绑定,但这并非必需。

请参阅第 (7) 项中的显式数据绑定示例。

2) 在哪里创建动态控件 - 在 Page_Init、Page_Load、LoadViewState 还是
PreRender?

最佳位置是 Page_Init 和 LoadViewState。LoadViewState 仅在 post
back 时调用。如果在此处完成,则在 Page_Load 中,您可以访问所有控件的 Postback
数据。

请阅读本文以了解页面生命周期。

也请看这篇关于动态控件的令人大开眼界的文章。

我试图通过创建几个 FAQ 来涵盖所有应该知道的内容。

是每个控件都应实现的一个方法。其职责可能
包括:http://aspalliance.com/articleViewer.aspx?
aId=134&pId
.http://weblogs.asp.net/infinitiesloop/archive/2006/08/25/TRULY-
Understanding-Dynamic-Controls-_2800_Part-1_2900_.aspx

3) 在哪里对控件进行数据绑定?

有两种解决方案:

  • 在 **ASCX** 文件中使用 **ObjectDataSource**,如第 (1) 项所述。**ASP.NET**
    在视图即将激活时,负责调用数据绑定。您所要做的
    就是将一些信息通过 **Initialize** 方法传递到控件,从父控件的
    ActiveIndexChanged 事件处理程序中传递,然后 *隐式* 数据绑定会自动
    在页面生命周期的正确阶段发生。
  • 在父控件 **MultiView** 中,从 **ActiveIndexChanged** 事件处理程序中调用 **Initialize**,该处理程序又执行 *显式* 数据绑定。由于 **ActiveIndexChanged**
    事件在 **ProcessPostBackData2**(参见页面生命周期)之后调用,这意味着
    如果此时发生数据绑定,并且因此创建了动态控件,那么您必须小心在
    视图的 postback 中重新创建这些控件。我将在下面进一步解释这一点。
    我将在下面进一步解释这一点。

**4) 如果我有一个 Repeater 或 FormView,它创建动态控件,处理创建过程的最佳事件是 ItemDataBound 还是 ItemCreated?**

ItemCreated 事件。

要使此模型正常工作,请在 ASCX 文件中声明 OnItemCreated 事件,而不是通过在 Page_Load 中附加事件,因为 Page_Load 在生命周期中发生得太晚了。我将在本节后面解释原因。
Page_Load 发生在生命周期中太晚了。我将在本节后面解释原因。
我将在本节后面解释原因。

**ItemDataBound 事件仅在 DataBinding 发生时调用。** ItemCreated
事件在 **DataBinding** 发生时和 PostBack 发生而没有 **DataBinding** 时都会被调用。

因此,创建动态控件的最佳位置是 ItemCreated 事件。当是 PostBack 时,ItemCreated 事件在 Page_Load 之前调用,此时 DataItem=NULL。当
当 ItemCreated 是由于 DataBinding 被调用时,DataItem != null。
DataItem != null。

PostBack 场景背后的情况是:ASP.NET 在 Repeater 控件的 LoadViewState 方法中重新创建 Repeater 中的每个项,
该方法会引发 ItemCreated 事件,此时 DataItem=NULL,因为没有发生数据绑定,
只有控件正在被重新创建。
只有控件正在被重新创建。

因此,如果在 ItemCreated 事件中 DataItem==NULL 且 Visible 属性为 true,则表示该控件正在可见状态下进行 PostBack。您可以在此处重新创建

动态控件,以确保在调用 Page_Load 时,您拥有这些控件的 Postback 数据。在此处添加有关动态创建的不可见
动态控件,以确保在调用 Page_Load 时,您拥有这些控件的 Postback 数据。在此处添加有关动态创建的不可见
控件的进一步讨论。
在此处添加有关动态创建的不可见控件的进一步讨论。

因此,在任何情况下,我都想不到需要从 Page_Load 中调用 Rebind。如果您
仍然需要这样做,那么由于 ItemCreated 事件发生在 Page_Load 之前,您可以
使用它来标记 PostBack 并实现自己的自定义逻辑。不要尝试在 Post Back 中从控件的 Page_Load 中 Rebind - 除非有令人信服的理由
Post Back 中从控件的 Page_Load 中 Rebind - 除非有令人信服的理由
在大多数情况下,让父容器处理。

例如,如果您有一个 Repeater,它在 PostBack 中添加项(子项),然后
需要重新绑定,一种方法是引发父控件的事件以重新绑定自身。另一种
方法是让页面自行处理,如上所述。

5) 我可以在 Prerender 中进行数据绑定吗?如果可以,我可以在那里创建动态控件吗?

是的,您可以,但请记住,在那里创建的任何动态控件在其 PostBack 中都将无法获得其 PostBackData。因此,在这样做时要小心。此外,在此时间附加到动态控件的任何事件
PostBackData。因此,在这样做时要小心。此外,在此时间附加到动态控件的任何事件
处理程序将根本不会被执行。

6) 如果我正在自己创建一个控件,而不是使用数据绑定控件,我该如何
在 PostBack 中初始化该控件(当它在 Multiview 中时)?

父 **Page_Load** 方法应负责调用创建的
控件的 **Initialize**,该方法又调用创建子动态控件。此时,子控件的 **Page_Load**
尚未调用,所以您可以直接在那里创建这些动态控件。如果您愿意,也可以调用 **DataBind**。

在 Web 页面的 **Page_Load** 处理程序中

protected void Page_Load(object sender, EventArgs e)
{
MultiView1.ActiveViewChanged += 
new EventHandler(MultiView1_ActiveViewChanged);

reviewDepControl.EditDependentClick +=
 new OnEditDependentEventHandler(OnEditDependentClick);

editDependentControl.DoneEditingDependent +=
 new OnDoneEditingDependentEventHandler(OnDoneEditingDependent);

//if not a postback, call init on the correct control
if (!IsPostBack)
{
if (MultiView1.ActiveViewIndex == 0)
{
reviewDepControl.Initialize(2, false);
}
else if (MultiView1.ActiveViewIndex == 1)
{
editDependentControl.Initialize(false);
}
}
else
{
if (MultiView1.ActiveViewIndex == 0)
{
reviewDepControl.Initialize(2, true);
}
else if (MultiView1.ActiveViewIndex == 1)
{
editDependentControl.Initialize(true);
}
}
}

在这里,第二个属性指示是否需要使用 **Rebind** 进行 **Initialize**。

MultiView 中还有一个 ActiveIndexChanged 事件,我们可以用它来重新绑定
控件,正如我在前面部分为首次初始化所解释的那样。

void MultiView1_ActiveViewChanged(object sender, EventArgs e)
{
if (MultiView1.ActiveViewIndex == 0)
{
reviewDepControl.Initialize(2, false);
}
else if (MultiView1.ActiveViewIndex == 1)
{
editDependentControl.Initialize(false);
}
}

还有另一种解决方案。在 PostBack 中使用控件的 LoadViewState 方法
来创建动态控件,但父控件可以调用 Initialize 方法来做一些
决定,如果需要的话。大多数情况下都不是这样。这个 Initialize 应该只在 Page_Load 中调用。
只在 Page_Load 中调用。

7) 尽量使用框架中可用的控件和 ObjectDataSource。
这将负责在正确的时间触发事件,而不是 putting your own custom logic
来模仿相同的功能 - 除非有令人信服的(且有效的)理由
如此行事。

8) 当 MultiView 的一个视图中有一个数据绑定控件时,如何在 PostBack 中调用
Initialize 方法来确保动态

控件已正确创建?

您不能使用 6) 中描述的方法来处理数据绑定控件,仅用于在 PostBack 中创建
动态控件。您需要依赖我在
第 4 项中讨论的技术。使用 ItemCreated 事件。如果您需要示例,请给我发送电子邮件。

© . All rights reserved.