【问题标题】:c# find controls and control referencec# 查找控件和控件引用
【发布时间】:2009-08-03 20:29:28
【问题描述】:

如何在没有 ID 的情况下引用 c#(运行时)中的控件?

例如,我有一个页面,其中有一个表格。我将使用 xmlhttp 递归地加载此页面,因此我无法使用它的 id 来引用该表。 this.Page.Controls[2] 有什么影响吗?或Controls["Tables"][0]

我尝试使用名称this.Controls.Find("MyTableName", true);,但需要引用库System.Windows.Forms(我认为)但不知道如何添加它,因为'using System.' intellisense 看不到它。

我遍历了this.Controls 中的所有控件,但'system.ui.web.control' does not contain a definition for '.Name' 所以我只能搜索 ID。

我是新手,我相信解决方案非常简单。
提前致谢

【问题讨论】:

  • 我想我不太明白——在页面生命周期的哪个部分,您会为加载客户端的 DOM 请求服务器端?
  • 数据集显示在一个太大而无法一次加载的树中,因此我会在用户展开每个节点时动态加载它。

标签: c# asp.net controls


【解决方案1】:

要在页面上查找控件,它必须是服务器控件,如下所示:

<asp:Table runat="server">
   ...
</asp:Table>

页面上的常规 HTML 不是“控件”,它们只是发送到浏览器的文本。另一方面,服务器控件是可以与代码隐藏交互的实际 .NET 类。

您仍然可以通过搜索其容器的 Controls 集合或递归搜索页面来获取此控件的句柄,而无需其 ID。让我们从递归搜索 Controls 集合开始:

Controls 集合仅引用给定控件的立即子控件。或页面的直接子控件。这些控件有自己的子控件。它代表内存中的一棵树。

这是一种从给定控件向下递归树并通过 ID 查找控件的方法:

private Control FindControlRecursive(Control control, string id)
{
    Control returnControl = control.FindControl(id);
    if (returnControl == null)
    {
        foreach (Control child in control.Controls)
        {
            returnControl = child.FindControlRecursive(id);
            if (returnControl != null && returnControl.ID == id)
            {
                return returnControl;
            }
        }
    }
    return returnControl;
}

(超出此答案的范围,最好使用extension method)。

要通过 ID 以外的其他内容查找控件,您可以按类型搜索:

if(someControl is System.Web.UI.WebControls.Table)

请注意,这通常不是一个好主意。如果您最终不得不以这种方式搜索控件,这不是一个很好的模式 - 您应该有一个控件的 ID,或者您应该已经有了对它的引用,因为它是在代码中创建的。

但是,修改递归搜索类型的方法很简单:

private Control FindTable(Control startFrom)
{
    foreach(Control child in startFrom.Controls)
    {
        if(child is System.Web.UI.WebControls.Table)
        {
            return child;
        }
        else
        {
            return FindTable(child);
        }
    }
    return null;
}

你也可以有这个方法的通用形式:

private Control FindControl<T>(Control startFrom)
{
    foreach(Control child in startFrom.Controls)
    {
        if(child.GetType().IsAssignableFrom(typeof(T)))
        {
            return child;
        }
        else
        {
            return FindControl<T>(child);
        }
    }
    return null;
}

您绝对不想包含 System.Windows.Forms,因为它只包含 WinForms 应用程序的所有代码。这就是为什么 Visual Studio 没有为你将它包含在 Web 项目中的原因——你永远不需要它。 System.Web.UI 拥有 Web 控件的一切。

【讨论】:

  • 我不知道为什么删除他的答案的那个人会投反对票 - 酸葡萄?因此,如果我使用您的想法按类型搜索什么参数类型确实定义为我的泛型类型,那么我也可以将我的方法发送到其他类型的控件。 if(myControl is arg)?
  • @Praesagus 我在演示搜索中添加了代码,而不是 ID。不过我不推荐使用这种方法...
  • 非常感谢您抽出宝贵时间回答所有这些问题。我采纳了您的建议并重组了代码,以便在运行时创建表,现在可以引用它。但是,我仍然有同样的问题,如果我将来需要,找不到没有 ID 的控件。
  • @Praesagus 我在回答中的观点是,您一开始就不需要这样做。如果您遇到需要这样做的情况,则表明您走错了路。像我提供的那种代码表明它在技术上是可行的,但它仍然是一个 hack。当您需要快速解决丑陋的情况时,黑客是可以的,但最好避免。
  • FindControlRecursive 方法中,您正在递归调用它,就像它是扩展方法一样:child.FindControlRecursive(id),但它不是,因此错误。因此,要么需要将方法更改为扩展方法,要么更改从内部调用它的方式:FindControlRecursive(child, id)
猜你喜欢
  • 1970-01-01
  • 2013-01-31
  • 1970-01-01
  • 2011-09-28
  • 2018-08-06
  • 2011-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多