【问题标题】:Stuck on Dynamic Controls, Viewstate, and Postback. Simplified example卡在动态控件、视图状态和回发上。简化示例
【发布时间】:2015-05-01 06:47:14
【问题描述】:

我一直在阅读帖子和链接,以及有关视图状态、状态包、回发和页面创建的文章。

我是一个相当不错的业余爱好者,但这个人并没有陷入困境,有人可以给我举个例子来说明如何做到这一点吗?

好的,这就是我想用这个例子做的事情

创建一个表,其中左列有链接按钮

当每个链接按钮被点击时,它会在右栏中打开一堆图像按钮

然后每个 Imagebutton 都会弹出一条消息

问题是imagebutton没有触发消息

这里是前端:

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="simple.aspx.vb" Inherits="simple" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>simple</title>
</head>
<body>
<form id="form1" runat="server">

<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>

<asp:Table id="MainTable" runat="server">
<asp:TableRow>

<asp:TableCell ID ="cell1" BackColor="LightBlue" />

<asp:TableCell ID ="cell2" BackColor="LightBlue" />

</asp:TableRow>
</asp:Table>

</form>
</body>
</html>

这里是代码:

Partial Class simple
Inherits System.Web.UI.Page

Protected Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init

    Dim NewTableButton As LinkButton = New LinkButton
    NewTableButton.Text = "Text Created from 1st SQL Query"
    AddHandler NewTableButton.Click, AddressOf LoadContacts

    cell1.Controls.Add(NewTableButton)

End Sub

Protected Sub LoadContacts(sender As Object, e As System.EventArgs)

    Dim TextPassedfromLinkButton As String = sender.text.ToString

    Dim imgGear As New ImageButton
    imgGear.ImageUrl = "../graphics/gear.jpg"
    imgGear.AlternateText = "Text Created from 2nd SQL Query using the " _
 & TextPassedfromLinkButton & " as a query parameter"
    AddHandler imgGear.Click, AddressOf message

    cell2.Controls.Add(imgGear)

End Sub

Protected Sub message(ByVal sender As Object, ByVal e As System.EventArgs)

    Dim strText As String = sender.text.ToString
    Dim alertString As String = "alert('" & strText & "');"
    ScriptManager.RegisterStartupScript(Me, [GetType](), "showalert", alertString, True)

End Sub

End Class

这是点击应该弹出消息的按钮后的视图源

 <table id="MainTable">
 <tr>
 <td id="cell1" style="background-color:LightBlue;"><a href="javascript:__doPostBack(&#39;ctl03&#39;,&#39;&#39;)">Text Created from 1st SQL Query</a></td>
 <td id="cell2" style="background-color:LightBlue;"><input type="image" name="ctl04" src="../graphics/gear.jpg" alt="Text Created from 2nd SQL Query using the Text Created from 1st SQL Query as a query parameter" /></td>
 </tr>
 </table>

所以与此同时,我得到了这个工作(更新 10:49 EST)

Protected Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init

    Dim NewTableButton As LinkButton = New LinkButton
    NewTableButton.Text = "Text Created from 1st SQL Query"
    'AddHandler NewTableButton.Click, AddressOf LoadContacts
    AddHandler NewTableButton.Click, Function() LoadContacts(NewTableButton.Text)

    cell1.Controls.Add(NewTableButton)

    If IsPostBack Then
        LoadContacts(NewTableButton.Text)
    End If

End Sub

Private Function LoadContacts(strText As String) As Integer

    Dim TextPassedfromLinkButton As String = strText

    Dim imgGear As New ImageButton
    imgGear.ID = "uniquename"
    EnableViewState = False
    imgGear.ImageUrl = "../graphics/gear.jpg"
    imgGear.AlternateText = "Text Created from 2nd SQL Query using the " & TextPassedfromLinkButton & " as a query parameter"
    AddHandler imgGear.Click, AddressOf message

    cell2.Controls.Add(imgGear)

    Return 0

End Function

唯一的问题是我得到 2 个相同的 imgGears

duplicate buttons http://reinsmith.net/graphics/simple1.png message displayed http://reinsmith.net/graphics/simple2.png

【问题讨论】:

    标签: asp.net vb.net postback viewstate


    【解决方案1】:

    这里的问题是您正在实例化 imgGear 按钮在另一个按钮的事件处理程序期间

    这样做似乎完全合乎逻辑,但是如果 imgGear 在页面生命周期中太晚创建并添加到控件树中,则永远不会触发 imgGear 的事件处理程序,例如在事件处理程序中或在 OnPreRender 期间。

    使用标准的 .Net 实践很难实现您想要做的事情......我从未管理过它。您可能还会注意到,在事件处理程序期间添加的文本框通常不会在回发时保留其值,这也是因为它在页面生命周期中添加得太晚了。

    您确实需要在 OnInit 或 CreateChildControls 期间检测上下文,因为在该阶段实例化并添加到控件树的按钮会触发其处理程序。

    不过,我已经开发了一种变通方法...与大多数变通方法一样,它并不漂亮...但它可以让您摆脱困境:

    在 OnInit 期间,您可以判断您的按钮是否导致回发,如果它是成员变量。在构造函数中初始化 NewTableButton...然后您可以检测它是否在 OnInit 期间被单击...

       Private NewTableButton as Button
    
       Public Sub New()
            MyBase.New()
            NewTableButton = New LinkButton
            NewTableButton.Text = "Text Created from 1st SQL Query"
        End Sub
    
        Protected Overrides Sub OnInit(e As EventArgs)
            MyBase.OnInit(e)
            cell1.Controls.Add(NewTableButton)
            If Not IsNothing(Page.Request(NewTableButton.UniqueID)) Then
               ' Create and add imgGear Button
               LoadContacts
            End If
        End Sub
    

    但是,文本框/下拉值在 OnInit 期间使用标准做法不可用...因此,您可能必须 a) 将它们的读取推迟到 OnPreRender,或 b) 使用 Page.Request(Control. UniqueID) 在 OnInit 期间读取输入控件的值。

    这是我在 .Net Web 开发中遇到的最大问题之一,它会让人头疼,而且我不喜欢变通...

    我很想知道是否有替代此解决方法的方法,但这是我发现实现您想要实现的目标的唯一方法。

    【讨论】:

    • 好的,现在是有趣的部分。这是一个简化的例子。我真正想做的是首先从带有客户名称的 SQL 查询中创建一组链接按钮。然后,当单击 LinkBut​​ton 时,获取单个客户名称并显示具有该客户名称的记录。例如每个客户的个人联系人。然后为每个联系人创建一个链接或按钮以在模式弹出窗口中编辑该个人联系人。因此,如果我可以检测到发送请求的单个控件并从中提取一些变量,那么覆盖就可以工作,这有意义吗?
    • 老兄,你现在已经改变了问题。我帮助您了解了原始问题并为您提供了解决方法。如果你能表达你的感激之情而不是改变问题,那就太好了。
    • 我很抱歉,我很感激它并且正在工作(我认为)我在过去的几天里有很多火灾要扑灭并且能够恢复它。希望我今天能做到。再次感谢,无意冒犯,特别是对少数能够做出回应的人!
    • 我不能说太多,谢谢!我终于花时间了解您的解决方案,当然它有效。我将用它来重新设计我的最终设置。再次感谢您提醒我花时间。
    【解决方案2】:

    这里的问题是关于页面生命周期,以及事件是如何连接的。当您已经进入页面生命周期的事件处理程序阶段时,为新控件连接事件为时已晚。您需要在此过程的早期进行操作才能使其正常工作。

    为了解决这个问题,我可以想到 3 种对 Webforms 更友好的潜在方法。

    1. 通过创建Repeater 控件、DataGridView 或类似控件并将Sql 查询的结果绑定到该控件来使用数据驱动的方法。此解决方案的一部分可能涉及编写一些原始 html/javascript 以与转发器一起使用,并与 WebMethod 结合使用,以使您的事件主要保持在客户端,并完全避免导致完全回发。鉴于我们已经知道您有一个 SQL 查询,这似乎是最合适的。
    2. 创建空的占位符控件,并将Visible 属性设置为False,以获取所需的所有可能控件。然后在运行时将数据分配给现有控件,并且只为您实际使用的那些控件将Visible 设置为True。当您知道项目数量相对较少且具有最大上限时,这通常是最佳选择。
    3. 开发一个自定义控件,将 ImageButton/Message/Event 概念封装到单个控件中。

    此外,您对另一个答案的评论表明您可能需要考虑使用单独的页面来查看/编辑单个客户与查看所有客户(可能使用查询字符串参数)。在此页面中,对于模式弹出窗口,我将其放入 div 中,其中支持弹出窗口的数据和其他所有内容已经加载在页面的开头,只需使用 javascript ,而不是服务器代码,来更改页面 DOM 以显示或隐藏弹出窗口。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-26
      • 2011-01-26
      • 1970-01-01
      相关资源
      最近更新 更多