asp.net的FindControl递归 [英] asp.net FindControl Recursively

查看:138
本文介绍了asp.net的FindControl递归的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个非常奇怪的关系 - 我会尽我所能解释

This is a really weird one - I will do my best to explain.

我有一个基本的母版页:

I have a basic master page:

<%@ 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>

我对递归地找到控制下的扩展方法:

I have the following extension methods for finding controls recursively:

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

我有一个列表视图控件:

I have a control with a 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>

这是数据绑定:

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

我有第二个控制,这是非常基本的:

I have a second control that is very basic:

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

在我的子页面,我有以下的code加载控件:

In my child page, I have the following code to load the controls:

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

这加载控件,但如果我点击列表视图测试按钮,页面中失去回发后列表视图中的数据。

This loads the controls, but if I click the Test button in the listview, the page loses the data in the listview after postback.

如果我改变FindControlRecursively调用FindControlIterative,当我点击测试按钮,在列表视图中的数据回传后保留。

If I change the FindControlRecursively calls to FindControlIterative, when I click the test button, the data in the listview is retained after the postback.

任何人有任何的想法是什么FindControlRecursively调用可能会做会导致列表视图失去它的数据吗?如果控制-2被添加到页面这只发生 - 如果不是的话,和控制-1被使用FindControlRecursively加载中,数据被回发后正确地保留

Anybody have any idea what the FindControlRecursively call might be doing to cause the listview to lose it's data? This only happens if control-2 is added to the page - if it is not, and control-1 is loaded using FindControlRecursively, data is retained correctly after postback.

在此先感谢......这个人是我发疯,我花了一段时间才能弄清楚究竟在那里它被打破。

Thanks in advance...this one is driving me nuts, and it took me a while to figure out where exactly it was breaking down.

推荐答案

你为什么不干脆公开返回属性 PH1 PH2 ,因为主机拥有他们的参考,你并不需要遍历掌握所有子控件:

Why don't you simply expose properties that return PH1 and PH2, because the master has the reference of them and you don't need to iterate all child controls of master:

Public ReadOnly Property Container1 As PlaceHolder
    Get
        Return Me.PH1
    End Get
End Property

Public ReadOnly Property Container2 As PlaceHolder
    Get
        Return Me.PH2
    End Get
End Property

您可以访问它们:

Dim ph1 As PlaceHolder = DirectCast(Me.Master, myMaster).Container1
Dim ph2 As PlaceHolder = DirectCast(Me.Master, myMaster).Container2

另一个问题是这一行:

Another problem is this line:

controlInstance1.ID = "control_2"

您的设置仅controlInstance1的ID两次,但不会导致您的问题。

You are setting only controlInstance1's ID twice, but that doesn't cause your issue.

您主要问题是,您要添加的控件在Page_Init而不是Page_Load中的占位符。因此,用户控件无法加载自己的ViewState和ListView控件是空的。他们重新在Page_Load中,它会正常工作。

Your main problem is that you are adding the controls to the placeholders in Page_Init instead of Page_Load. Therefore the UserControls can't load their ViewState and the ListView is empty. Recreate them in Page_Load and it will work.

修改:但我必须承认,我不知道为什么你的迭代扩展战胜递归。在占位符的参考是相同的,他们不应该工作两者不可思议。

Edit: But i must admit that i don't know why your iterate extension wins over the recursive. The reference on the placeholders are the same, they shouldn't work both, weird.

摘要


  • 它与我的楼盘,

  • 把所有页面的加载事件处理程序,而不是初始化

  • 与迭代扩展(无论何种原因)

它也可以,如果你在最后添加这两个用户控件,您通过 FindControlRecursively 发现占位符后。

It also works if you add both UserControls at last, after you've found the placeholders via FindControlRecursively.

zone.Controls.Add(controlInstance1)
zone2.Controls.Add(controlInstance2)

我失去了这个动机,但我相信你会找到答案的 这里 Controls.Add被加载它的父的ViewState到所有儿童的,因此这取决于当你添加控件,也在他们的父控件控件的索引必须在回发相同的重新加载ViewState中。

I'm losing motivation on this, but i'm sure you'll find the answer here. Controls.Add loads it's parent's ViewState into all childs and therefore it depends on when you add the controls, also the index of the controls in their parent controls must be the same on postback to reload the ViewState.

您递归扩展方法倒是你把它添加到PH1(同时搜索PH2)之后,控制1的ID,迭代扩展没有。我认为这会破坏它在Page_Init ViewState中。

Your recursive extension method touches control1's ID after you've added it to PH1(while searching PH2), the iterative extension does not. I assume that this corrupts it's ViewState in Page_Init.

结论使用属性,而不是

这篇关于asp.net的FindControl递归的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆