具有两个模板的模板化用户控件如何在其他模板中查找需要控件id的属性的控件

本文关键字:控件 其他 id 属性 查找 用户 两个 | 更新日期: 2023-09-27 18:08:25

我有一个模板化的用户控件与两个模板,一切都工作,除了设置id的东西,如AssociatedControlID或ControlToValidate的控件存在于另一个模板。

我知道它们存在于两个不同的命名容器中,这阻止了它们找到彼此,所以在下面的代码中设置AssociatedControlID不只是与控件id一起工作。是否有一些技巧可以声明式地设置它,或者我必须使用FindControl并在后面的代码中设置它?

这是我的控件布局:

<uc1:Field ID="paramName" runat="server">
    <LabelTemplate >
        <asp:Label ID="lblName" AssociatedControlID="txtValue" runat="server" >Label Text:</asp:Label>
    </LabelTemplate>
    <InputTemplate>
        <asp:TextBox ID="txtValue" runat="server" MaxLength="30"></asp:TextBox>
    </InputTemplate>
</uc1:Field>

EDIT 1:我甚至不能让它在后面的代码中设置它。我尝试将AssociatedControlID设置为。id,。clientid,。uniqueid。我总是忘记哪个是必需的,所以我尝试了所有这些。我也试着从FindControl中找到控件。我能够从控件的父控件中找到它,但不是父控件的父控件。这很奇怪。

编辑2:我已经想出了一个部分解决方案。它不为AssociatedControlID工作,但它确实为ControlToValidate工作,这对我来说更重要。这里是解决方法:在容器类中,您必须重写FindControl,并使其指向两层。然后你需要做你自己的FindControl,因为我尝试了Parent.Parent.FindControl,它仍然没有找到控件,我不完全明白为什么,所以我有一个扩展方法来枚举控件集合中的所有控件。我也不知道为什么它不与AssociatedControlID标签工作。也许在内部它调用FindControl的方式不同

我仍然觉得我错过了一些简单的东西。

/// <summary>
/// This is a hack to get the validators in the label template to see the controls in the input template
/// just don't name any controls in the two templates the same thing
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public override Control FindControl(string id)
{
    if (Parent == null && Parent.Parent == null)
    {
        return base.FindControl(id);
    }
    return Parent.Parent.Controls.All().Where(x => x.ID == id).FirstOrDefault();
}

下面是All扩展方法:

public static IEnumerable<Control> All(this ControlCollection controls)
{
    foreach (Control control in controls)
    {
        foreach (Control grandChild in control.Controls.All())
            yield return grandChild;
        yield return control;
    }
}

谢谢你帮我解决这个烦人的问题。

克里斯

具有两个模板的模板化用户控件如何在其他模板中查找需要控件id的属性的控件

对于ControlToValidate,您可以在InputTemplate控件的类定义上使用ValidationPropertyAttribute。只需将代码更新为:

//"Text" is the name of the Property which returns the value to validate
[ValidationProperty("Text")] 
public class InputTemplate
{
    ...
    public string Text { set { txtValue.Text = value; } get { return txtValue.Text } }
}

现在在你的代码后面,你可以设置你的RequiredFieldValidator的ControlToValidate属性为用户控件的ID:如。RequiredFieldValidator1.ControlToValidate = InputTemplate1.ID;

至于标签的AssociatedControlID,我还没有弄清楚。

祝你好运,

肖恩