新社区网站

通常,你会在正确的地方,但我们最近推出了一个全新的社区网站……为社区,受社区。

耶……带我去社区!

社区博客是社区成员的个人观点,绝不是DNN公司或DNN平台的官方立场。这是一个表达个人对DNNPlatform、社区及其生态系统的想法的地方。你有什么有用的信息想要与DNN社区分享吗?如果有,请联系

社区博客的使用由我们的社区博客指南-请在评论或发布之前阅读。


动态控件、回发和视图状态数据

小君 14

许多开发人员使用一种众所周知的技术将.ascx动态加载到另一个自定义的.ascx中。这种技术被应用于后面的代码中,并且有许多开发人员创建的代码的许多变体。

您可能知道的第一件事是,当控件加载到asp.net页面中时,每次向服务器发出回发请求时都必须加载它,因为它需要每次呈现自己,直到我们决定使用新控件。

当动态加载的控件试图从视图状态读取/写入数据时,以及加载器控件试图这样做时,我们的问题就开始了。问题是viewstate数据仅在页面生命周期的几个步骤之间是活动的,我们将看到这一点。

看看下面的代码:

Protected Sub RadioButtonList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)处理RadioButtonList1。SelectedIndexChanged
LoadControls ()
终止子
Private Sub LoadControls()
Dim c As控制
如果RadioButtonList1。SelectedValue= "1" Then
c = LoadControl(" control1.ascx")
其他的
c = LoadControl("control2.ascx")
如果
c.ID = RadioButtonList1。SelectedValue
PlaceHolder1.Controls.Clear ()
PlaceHolder1.Controls.Add (c)
终止子


受保护的子Page_Load(ByVal发送者作为对象,ByVal e作为System.EventArgs)处理我。负载
LoadControls ()
如果不是Page。IsPostBack然后
DataList1。数据源=值
DataList1.DataBind ()
如果
终止子

如您所见,代码尝试根据下拉列表中存储的值加载子控件。在第一次,这段代码将工作良好,之后,你会开始发现一些问题

问题1:IsPostBack属性不能在子控件中使用

如您所知,用于验证页面是第一次加载还是为回发而加载的最常用代码是IsPostBack变量。

如果不是isPostBack,那么
DoMyWork ()
如果

回顾我们的代码,我们会发现:

a)第一次进入页面:

主控件加载由单选按钮列表中的默认值指定的默认控件(即Control1)。子控件加载正常,IsPostBack变量为false(如预期)

b)单击单选按钮列表,选择另一个选项

主控件加载新控件(即控件2)。子控件加载,我们测试IsPostBack属性的代码将发现它的值等于true(该事件是通过单击单选按钮列表产生的真实回发)。

c)再次点击单选按钮列表,再次选择默认选项

主控件加载控件(Control1),然后Control1再次加载。控件将发现IsPostback变量等于true

在C中加载的控件将期望一个等于“false”的值来初始化它自己的内容,并且该值将仅在第一次加载页面时提供。

解决方案:使用viewstate标志来检查代码是否已经初始化

如果不是,viewstate("MyFlag")则为空

DoMyWork ()

视图状态(“MyFlag”)=“Ok”

如果

问题2:当控件未在页面生命周期的INIT部分实例化时,某些视图状态数据不可用

让我们回顾一下页面生命周期:

  1. 初始化
  2. LoadViewState(只发生在PostBack)
  3. LoadPostDackData(只发生在PostBack)
  4. 负载
  5. RaisePostBacKEvent(只发生在PostBack上)
  6. SaveViewState
  7. 渲染

从我们的示例中可以看到,直到“Load”阶段,我们才重新创建动态控件。到那时,LoadViewState和LoadPostBackData已经发生了。在加载事件发生时,我们的控件已经创建,所有的数据都没有被它们加载。

因此,我们需要在以前的状态下创建控件。查看我们的控件事件,我们会发现最接近的选项是INIT事件,我们将代码移动到INIT事件。

我们的单选按钮列表的值总是等于默认选择!!为什么?

答案很简单,看一下页面的生命周期。Init事件发生在LoadViewState和LoadPostBackData之前,并且主控件的代码还没有关于单选按钮的任何数据。

因此,我们在这里遇到了一个真正的问题,因为在第一种情况下,子控件的数据丢失了,而在第二种情况下,父控件的数据还没有准备好,我们仍然需要它工作。

解决方案:尽管大多数论坛或博客上的一般规则都说最好不要这样做,但是ASP的完美之处在于。NET和DotNetNuke就是你可以用一点想象力做你想做的一切

我们的主要问题是,我们需要在阶段3之前重新创建控件,并且在阶段1中没有视图状态数据。

我们的控件是通过使用OOP(面向对象编程)构建的,因此我们可以覆盖基类中的一些函数。例如,没有什么可以阻止我们重写LoadViewState函数:


Protected覆盖子LoadViewState(ByVal savedState作为对象)
MyBase.LoadViewState (savedState)
CreateMyControls ()
终止子
由于问题似乎只有在回发到位时才会出现,因此我们可以在viewstate中创建一个标志,以便在最近覆盖的函数中重新创建控件
Protected覆盖子LoadViewState(ByVal savedState作为对象)
MyBase.LoadViewState (savedState)
如果不是,viewstate(" MyFlag ")则为空
CreateMyControls ()
视图状态(“MyFlag”)=“Ok”
如果
终止子

在以下几行中可以找到经过改进的最终示例:


Protected Sub RadioButtonList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)处理RadioButtonList1。SelectedIndexChanged
选择Case RadioButtonList1。SelectedValue
“1”
LoadUserControl(“MyControl1.ascx”)
“2”
LoadUserControl(“MyControl2.ascx”)
“3”
LoadUserControl(“MyControl3.ascx”)
其他情况下
LoadUserControl(“MyControl1.ascx”)
最终选择
终止子

Protected覆盖子LoadViewState(ByVal savedState作为对象)
MyBase.LoadViewState (savedState)
LoadControls ()
终止子

Private Sub LoadControls()
如果不是我。latestloaddcontrolname是空的
LoadUserControl(我。LatestLoadedControlName Me.LatestLoadedControlAjax)
其他的
LoadUserControl(“urlcontrolfile.ascx”)
如果

终止子

私有属性latestloaddcontrolname()作为字符串
得到
返回装运箱(视图状态(“LatestLoadedControlName”))
最终得到
设置(ByVal值作为字符串)
ViewState("LatestLoadedControlName") = value
终端设置
结束财产

公共子LoadUserControl(ByVal controlName作为字符串,可选ByVal useAjax作为布尔值= False)
如果不是(latestloaddcontrolname Is Nothing)那么
Dim previousControl As Control = PlaceHolder1.FindControl(LatestLoadedControlName.Split("。"c)(0))
如果不是(previousControl Is Nothing)那么
PlaceHolder1.Controls.Remove (previousControl)
如果
如果
Dim userControlID As String = controlName.Split("."c)(0)
Dim targetControl As Control = placeholder . findcontrol (userControlID)
如果targetControl为空,则
将userControl设置为Control = none
userControl = LoadControl(controlName)
用户控件。ID = userControlID。取代 ("/", "").替换(“~”,“”)
PlaceHolder1.Controls.Add(用户)
LatestLoadedControlName = controlName
如果
终止子

评论

评论形式

只有注册用户才能发表评论。

NewsArchives


Aderson Oliveira(22岁)
亚历克·惠廷顿(11岁)
亚历山德拉·戴维斯(3岁)
Alex Shirley(10岁)
安德鲁·霍夫林(3岁)
安德鲁·纳斯(30岁)
安迪·特里巴(1)
安东尼·格伦赖特(5岁)
安东尼奥·夏格里(28岁)
阿什·普拉萨德(37岁)
本·施密特(1)
本杰明·赫尔曼(25岁)
伯努瓦·萨顿(9岁)
贝丝·费尔堡(12岁)
比尔·沃克(36岁)
鲍勃·克鲁格(5岁)
波格丹·莱特斯库(1)
布莱恩·杜克斯(2岁)
白雪皑皑(1)
布鲁斯·查普曼(20岁)
布莱恩·安德鲁斯(1)
卡塔·康诺利(55岁)
查尔斯·纳斯(163)
克里斯·哈蒙德(第213届)
克里斯·帕特拉(55岁)
克林特·帕特森(108)
邝党(21岁)
丹尼尔·巴塞洛缪(2岁)
丹尼尔·梅特勒(181)
丹尼尔·瓦拉达斯(48岁)
戴夫·巴克纳(2岁)
大卫·波因德克斯特(12岁)
大卫·罗德里格斯(3岁)
萧耀文(1)
道格·豪厄尔(11岁)
Erik van Ballegoij(30岁)
恩斯特·彼得·塔明加(80岁)
弗朗西斯科·佩雷斯·安德烈斯(17岁)
杰夫·巴洛(12岁)
乔治·阿拉特拉什(12岁)
吉福德·沃特金斯(3)
吉尔·勒·皮戈彻(3)
伊恩·罗宾逊(7岁)
以色列·马丁内斯(17岁)
简·布洛姆奎斯特(2)
简·乔纳斯(3岁)
贾斯普雷特·巴蒂亚(1)
詹妮·梅里菲尔德(6岁)
乔·布林克曼(274)
约翰·米切尔(1)
乔恩·亨宁(14岁)
乔纳森·希利(4岁)
乔丹·库珀史密斯(1)
约瑟夫·克雷格(2岁)
马侃(1)
凯文贝吉(3岁)
凯利·福特(4岁)
肯·格里尔森(10岁)
凯文·施莱纳(6岁)
利·波因特(31岁)
洛林·杨(60岁)
Malik Khan (1)
马特·拉特利奇(2岁)
马蒂亚斯·施洛曼(16岁)
毛里西奥Márquez (5)
迈克尔·多克西(7岁)
迈克尔·托比什(3岁)
迈克尔·华盛顿(2002)
米格尔·加梅坦(3)
迈克·霍顿(19岁)
米歇尔·塞勒斯(40岁)
弥敦罗孚(3)
Navin V Nagiah(14岁)
n (31)
Nik Kalyani(14岁)
奥利弗·海因(1)
帕特里西奥·f·萨利纳斯(1)
帕特里克·瑞恩(1)
彼得·唐克(54岁)
菲利普·比德尔(135岁)
菲利普·贝克尔(4岁)
理查德·杜马斯(22岁)
罗伯特·J·柯林斯(5岁)
罗杰·塞尔温(8岁)
鲁本·洛佩兹(1)
莱恩·马丁内斯(1岁)
Sacha Trauwaen (1)
爱沙尼亚语(4)
Sanjay Mehrotra(9岁)
斯科特·麦卡洛克(1)
斯科特·施莱西尔(11岁)
斯科特·威尔金森(3岁)
斯科特·威尔海特(97岁)
塞巴斯蒂安·洛波德(80岁)
肖恩·沃克(237)
肖恩·梅哈菲(17岁)
斯蒂芬·卡尔曼(12岁)
Stefan Kamphuis(12岁)
史蒂夫·法比安(31岁)
史蒂文·费舍尔(1)
蒂莫·布鲁梅尔霍夫(24岁)
托尼·亨利克(3岁)
托斯滕·韦根(3岁)
第谷·德·沃德(4)
Vicenç Masanas(27岁)
Vincent Nguyen(3岁)
维塔利·科扎达耶夫(6岁)
威尔·摩根维克(40岁)
威尔·斯特罗尔(180岁)
威廉·塞弗伦斯(5岁)
什么是液体含量?
找出
什么是液体含量?
找出
什么是液体含量?
找出
Baidu
map