gpt4 book ai didi

asp.net 递归查找控件

转载 作者:行者123 更新时间:2023-12-02 18:50:53 25 4
gpt4 key购买 nike

这真的很奇怪 - 我会尽力解释。

我有一个基本的母版页:

<%@ Master Language="VB" CodeFile="MasterPage.master.vb" Inherits="master_MasterPage" %>

<!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">
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
<asp:PlaceHolder ID="PH1" runat="server" />
<asp:PlaceHolder ID="PH2" runat="server" />
</div>
</form>
</body>
</html>

和一个标准子页面:

  <%@ Page Title="" Language="VB" MasterPageFile="~/master/MasterPage.master" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="master_Default" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
</asp:Content>

我有以下扩展方法用于递归查找控件:

Option Strict On
Option Explicit On

Imports System.Runtime.CompilerServices
Imports System.Web.UI

Public Module ExtensionMethods

<Extension()> _
Public Function FindControlRecursively(ByVal parentControl As System.Web.UI.Control, ByVal controlID As String) As System.Web.UI.Control

If parentControl.ID = controlID Then
Return parentControl
End If

For Each c As System.Web.UI.Control In parentControl.Controls
Dim child As System.Web.UI.Control = FindControlRecursively(c, controlID)
If child IsNot Nothing Then
Return child
End If
Next

Return Nothing

End Function

<Extension()> _
Public Function FindControlIterative(ByVal rootControl As Control, ByVal controlId As String) As Control

Dim rc As Control = rootControl
Dim ll As LinkedList(Of Control) = New LinkedList(Of Control)

Do While (rc IsNot Nothing)
If rc.ID = controlId Then
Return rc
End If
For Each child As Control In rc.Controls
If child.ID = controlId Then
Return child
End If
If child.HasControls() Then
ll.AddLast(child)
End If
Next
rc = ll.First.Value
ll.Remove(rc)
Loop

Return Nothing

End Function

End Module

我有一个带有 ListView 的控件:

<%@ Control Language="VB" AutoEventWireup="false" CodeFile="control-1.ascx.vb" Inherits="controls_control_1" %>
<p>
Control 1</p>
<asp:ListView ID="lv" runat="server">
<ItemTemplate>
<div>
<asp:Literal ID="Name" runat="server" Text='<%#Eval("Name") %>' />
<asp:LinkButton ID="TestButton" runat="server">Test</asp:LinkButton>
</div>
</ItemTemplate>
</asp:ListView>

这是数据绑定(bind):

Partial Class controls_control_1
Inherits System.Web.UI.UserControl

Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then

Dim l As New List(Of Person)
Dim j As New Person
j.Name = "John"
l.Add(j)

lv.DataSource = l
lv.DataBind()

End If

End Sub

End Class

Public Class Person
Public Property Name As String
End Class

我有第二个非常基本的控件:

<%@ Control Language="VB" AutoEventWireup="false" CodeFile="control-2.ascx.vb" Inherits="controls_control_2" %>
<p>Control 2</p>

在我的子页面中,我有以下代码来加载控件:

Option Strict On
Option Explicit On

Partial Class master_Default
Inherits System.Web.UI.Page

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

Dim controlInstance1 As System.Web.UI.Control = LoadControl("~/controls/control-1.ascx")
controlInstance1.ID = "control_1"

Dim zone As System.Web.UI.Control = Me.Master.FindControlRecursively("PH1")

zone.Controls.Add(controlInstance1)

Dim controlInstance2 As System.Web.UI.Control = LoadControl("~/controls/control-2.ascx")
controlInstance2.ID = "control_2"

Dim zone2 As System.Web.UI.Control = Me.Master.FindControlRecursively("PH2")

zone2.Controls.Add(controlInstance2)

End Sub

End Class

这会加载控件,但是如果我单击 ListView 中的“测试”按钮,页面在回发后会丢失 ListView 中的数据。

如果我将 FindControlRecursively 调用更改为 FindControlIterative,当我单击测试按钮时, ListView 中的数据将在回发后保留。

有人知道 FindControlRecursively 调用可能会做什么导致 ListView 丢失其数据吗?仅当将 control-2 添加到页面时才会发生这种情况 - 如果没有添加,并且使用 FindControlRecursively 加载 control-1,则数据在回发后会正确保留。

提前致谢...这让我发疯,我花了一段时间才弄清楚它到底是在哪里崩溃的。

最佳答案

我明白了为什么我会看到上面描述的行为。我将递归函数更改为以下内容:

<Extension()> _
Public Function FindControlRecursively(ByVal parentControl As System.Web.UI.Control, ByVal controlId As String) As System.Web.UI.Control

If String.IsNullOrEmpty(controlId) = True OrElse controlId = String.Empty Then
Return Nothing
End If

If parentControl.ID = controlId Then
Return parentControl
End If

If parentControl.HasControls Then
For Each c As System.Web.UI.Control In parentControl.Controls
Dim child As System.Web.UI.Control = FindControlRecursively(c, controlId)
If child IsNot Nothing Then
Return child
End If
Next
End If

Return Nothing

End Function

通过添加 parentControl.HasControls 检查,我阻止该函数在 ListView 中搜索子控件,这允许 ListView 稍后在页面/控件生命周期中加载其 View 状态。

此外,我还调整了迭代函数,使其更加高效,并防止在未返回控件时出现错误:

<Extension()> _
Public Function FindControlIteratively(ByVal parentControl As Web.UI.Control, ByVal controlId As String) As Web.UI.Control

Dim ll As New LinkedList(Of Web.UI.Control)

While parentControl IsNot Nothing
If parentControl.ID = controlId Then
Return parentControl
End If
For Each child As Web.UI.Control In parentControl.Controls
If child.ID = controlId Then
Return child
End If
If child.HasControls() Then
ll.AddLast(child)
End If
Next
If (ll.Count > 0) Then
parentControl = ll.First.Value
ll.Remove(parentControl)
Else
parentControl = Nothing
End If
End While

Return Nothing

End Function

另外,为了跟进我之前对问题的描述 - 如果我删除了 If child.HasControls() Then 检查,我就能够使用迭代函数重现递归函数最初奇怪的行为从迭代函数。希望这是有道理的。

最后我坚持使用迭代函数,因为循环应该比递归更便宜,尽管在现实场景中差异可能不会明显。

以下链接对我解决这个问题非常有帮助:

http://msdn.microsoft.com/en-us/library/ms972976.aspx#viewstate_topic4

https://web.archive.org/web/20210330142645/http://www.4guysfromrolla.com/articles/092904-1.aspx

http://scottonwriting.net/sowblog/archive/2004/10/06/162995.aspx

http://scottonwriting.net/sowblog/archive/2004/10/08/162998.aspx

特别感谢蒂姆为我指明了正确的方向。

关于asp.net 递归查找控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5276573/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com