ASP.NET动态数据:使用列名从FormView查找DynamicControl的数据控件

时间:2014-05-22 20:08:58

标签: asp.net custom-attributes dynamic-controls asp.net-dynamic-data

问候StackOverflow,

TL; DR

在字段模板控件的OnLoad方法中,如何按属性或列名称查找FormView中其他字段的数据控件。

END TL; DR。

我正在尝试向Boolean_Edit字段模板添加一些逻辑,这样如果绑定到它的属性有一个新属性,我就会模板注入JavaScript。 JavaScript旨在禁用属性的ControlledFieldNames属性中列出的列/属性名称的所有数据控件。

这有点令人困惑,所以我会分享一些代码。

这是我为此做的属性类:

/// <summary>
/// Attribute used to insert javascript into an ASP.NET web page that uses Dynamic Controls so that if the field's value changes it disables (or enables) 
/// other web controls on the page which correspond to the other bound property names.
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = true)]
public sealed class InputRestrictorFieldAttribute : Attribute
{
    public Boolean TargetEnabledState { get; set; }
    public String[] ControlledFieldNames { get; set; }

    public InputRestrictorFieldAttribute(Boolean targetEnabledState, params String[] controlledFieldNames)
    {
        this.TargetEnabledState = targetEnabledState;
        this.ControlledFieldNames = controlledFieldNames;
    }
}

所以我可能在某些脚手架类中有一个属性,如:

[ScaffoledTable(true)]
public class Person
{
    /* Other properties... */

    [InputRestrictorFieldAttribute(false, new String[]
    {
        "StreetAddress",
        "City",
        "State",
        "Zip"
    })]
    public Boolean AddressUnknown { get; set; }

    public String SteetAddress { get; set; }

    public String City { get; set; }

    public String State { get; set; }

    public String Zip { get; set; }

    /* some more code */
}

现在在Boolean_Edit.ascx.cs文件中,我试图检查当前的scaffold属性是否具有InputRestrictorFieldAttribute,如果是,则将JavaScript注入页面,以便在检查AddressUnknown CheckBox控件时已禁用StreetAddressCityStateZip的TextBox控件。

以下是我最近尝试过的内容。

protected override void OnLoad(EventArgs e)
{
    var attributes = this.Column.Attributes;
    foreach (Attribute attr in attributes)
    {
        if (attr is InputRestrictorFieldAttribute)
        {
            InputRestrictorFieldAttribute restrictor = (InputRestrictorFieldAttribute)attr;
            String restrictorScriptFunctionName = String.Format(RESTRICTOR_SCRIPT_FUNCTION_NAME, ClientID);
            String restrictorScript = String.Format(RESTRICTOR_SCRIPT_TEMPLATE_ONCLICK,
                restrictorScriptFunctionName,
                restrictor.BoundFieldNames.Aggregate("", (aggr, item) =>
                {
                    var bc = this.NamingContainer.BindingContainer;
                    var ctrl = bc.FindFieldTemplate(item);
                    return aggr + String.Format(RESTRICTOR_SCRIPT_TEMPLATE_ELEMENT, ctrl.ClientID);
                }));

            Page.ClientScript.RegisterStartupScript(Page.GetType(), "restrictorScript_" + ClientID, restrictorScript, true);
            CheckBox1.Attributes.Add("onchange", restrictorScriptFunctionName + "(this);");
        }
    }

        base.OnLoad(e);
    }

现在我知道要做的事情就是让this.NamingContainer.BindingContainer许多不(或可能不会)在其他页面中工作,但是现在(在Insert.aspx页面模板的上下文中)工作。 this.NamingContainer.BindingContainer是Insert.aspx页面的FormView1控件。但到目前为止,我尝试过各种各样的数据控件或字段模板,或者通过属性名称进行动态控制,它总是返回null或抛出异常。

最后,聚合方法只是将JavaScript片段连接在一起,以便只使用一个JavaScript函数停用所有控件。这些脚本的内容对这个问题并不重要。

1 个答案:

答案 0 :(得分:0)

有一个名为FindFieldTemplate的扩展方法,请参阅see it here