从ascx中查找对aspx的控制

时间:2009-06-16 19:22:54

标签: asp.net vb.net

我正试图在所述aspx页面上的用户控件(ascx)上找到aspx页面上的标签。显然,Page.FindControl(“lablel1”)无效。我需要在某处添加ClientID吗?感谢。

10 个答案:

答案 0 :(得分:14)

我认为你应该停下来思考你的设计。你的控件不需要知道包含它们的页面的任何信息 - 你需要从另一个控件中找到页面上的控件这一事实告诉我你应该重新考虑这个问题。

我可以告诉你的最好的事情(我对你的架构知之甚少)是你应该传递对你希望在用户控件中找到的控件的引用。这样你的控制就不必知道自己以外的事情了。

答案 1 :(得分:3)

在控件的直接父级的上下文之外使用FindControl()时,您需要遍历控制树以查找label所在的级别并在适当的位置调用.FindControl()水平。

那就是说,听取@Andrew Hare的建议并重新审视你的架构决策。有可能有更好的方法让UserControl与其消费页面进行交互。

例如,您可以在UserControl中公开公共事件,并将事件处理程序添加到您的使用页面(或基页/母版页)。创建事件时,您可以根据需要制作签名,因此请继续并包含需要传递的错误文本。

如果你想使用它,你可以将你的错误标签变成一个自定义控件,并挂钩事件。

示例事件:

Public Event UserErrorOccured(ByVal ErrorText as String)

示例错误:

If Not Page.IsValid Then
    RaiseEvent("The page is not valid")
End If

样本处理程序:

protected sub UserEventHandler(ByVal ErrorText as String) Handles MyUserControl.UserErrorOccured
    errorLabel.Text = ErrorText
End Sub

答案 2 :(得分:3)

如果层次结构是可预测的,那么这样的事情应该有效。

Me.Owner.FindControl("controlName")

...或

Me.Owner.Parent.FindControl("controlName")

...或

Me.Owner.Parent.Parent.FindControl("controlName")

如果它不可预测,那么你将不得不编写一个递归(昂贵)函数来代替控件。不过要小心你的方法,因为如果在大页面上过度使用,这种类型的算法会变得缓慢而且难以处理。

这是VB中用于向后搜索树(从子节点到父节点)并找到控件的示例:

Protected Function FindControlByID(ByRef childControl As Control, ByVal ID As String) As Control
    Dim ctrl As Control = childControl.FindControl(ID)
    If Not ctrl Is Nothing Then
      Return ctrl
    Else
      If Not childControl.Parent Is Nothing Then
        Return FindControlByID(childControl.Parent, ID)
      Else
        Return Nothing
      End If
    End If
  End Function

我会这样称呼它:

Dim lbl As Label = FindControlByID(Me.Owner, "label1")

答案 3 :(得分:2)

创建一个界面,例如:

public interface IStatusDisplayer
{
   Label StatusLabel { get; }
}

在显示错误/状态标签的任何页面上实现界面。如果您的用户控件需要访问标签,您可以执行以下操作:

var statusDisplayer = this.Page as IStatusDisplayer;
if (statusDisplayer != null)
{
    statusDisplayer.StatusLabel.Text = "Hello World!";
}

答案 4 :(得分:1)

来自用户控件

Me.NamingContainer.FindControl("label1")

答案 5 :(得分:1)

Control ct = WebUserControl11.FindControl("DropDownList1");

DropDownList dt = (DropDownList)ct;

TextBox1.Text = dt.SelectedValue.ToString();

答案 6 :(得分:0)

我想到了其他一些想法。 Page类中的“Items”集合可用于存储值或类似思想的Session对象。另一种方法是在页面上公开一个公共方法来更新标签。该架构可能存在AJAX问题,因为我不确定回调可以同时更新页面的多个区域,所以这只是一个警告,我不是说我遇到了这个问题。

TheSteve的答案也有效,我过去不得不这样做,虽然围绕控制可能很棘手。我也会回答安德鲁的回答。

答案 7 :(得分:0)

这很简单,首先您需要访问母版页ContentPlaceHolder:

Dim ContentPlaceHolder1 As ContentPlaceHolder = TryCast(Page.Master.FindControl("ContentPlaceHolder1"), ContentPlaceHolder)

然后使用ContentPlaceHolder,您现在可以在aspx页面上找到控件的ID:

TryCast(ContentPlaceHolder1.FindControl("LiteralOnParentASPXPage"), Literal).Text = "some text" 

答案 8 :(得分:0)

这是一种蛮力方法,但是当控件深深埋藏在控件层次结构中时它可以工作:

private Control GetTextEditor(ControlCollection controls)
{
    foreach (Control ctrl in controls)
    {
        if (ctrl.ID != null && ctrl.ID == "teMessage")
            return ctrl;
        if (ctrl.Controls.Count > 0)
        {
            Control inner = GetTextEditor(ctrl.Controls);
            if (inner != null)
                return inner;
        }
    }
    return null;
}

答案 9 :(得分:0)

访问意味着在.aspx文件中启用/禁用.ascx中的控件,尝试此代码它也是解决方案。

protected void Page_Load(object sender, EventArgs e)
{
    Control ct = PEM.FindControl("btnInsert");
    Button btn = (Button)ct;
    btn.Enabled = false;
}