繁体   English   中英

如何检测ASP.NET控件属性是否包含DataBinding表达式?

[英]How to detect if ASP.NET control properties contain DataBinding expressions?

我有一个自定义控件,该控件继承自System.Web.UI.Control ,可以使用数据绑定表达式声明性地设置其某些属性。 例如

<foo:Foo runat="server" MyFoo="<%# this.GetFoo() %>" />

现在,当我这样做时,我需要在控件(或.DataBind()控件之一.DataBind()上调用.DataBind() )来评估这些表达式。

我想做的是检测是否以这种方式设置了任何属性,并且只是在OnPreRender之后或之后自动使自定义控件调用this.DataBind()

所以问题来了 :如何检测数据绑定表达式是否正在等待执行?

我坚信在某些ControlBuilderDataBindContext类中可以包含确定此信息所需的信息。 我已经在Reflector周围搜寻,似乎找不到它。

我应该补充一点,如果没有以这种方式分配直接属性,我不想支付执行DataBind()的开销。 这就是为什么我想先发现。 该类非常轻巧,但是我希望能够以声明方式设置属性,而无需任何代码。

在深入研究ControlBuilder ,我注意到当存在数据绑定表达式时,每个控件实例的编译工厂将附加一个DataBinding事件处理程序。 我发现检查这一点似乎是确定是否需要进行数据绑定的一种非常可靠的方法。 这是我解决问题的基础:

using System;
using System.Reflection;
using System.Web.UI;

public class AutoDataBindControl : Control
{
    private static readonly object EventDataBinding;
    private bool needsDataBinding = false;

    static AutoDataBindControl()
    {
        try
        {
            FieldInfo field = typeof(Control).GetField(
                "EventDataBinding",
                BindingFlags.NonPublic|BindingFlags.Static);

            if (field != null)
            {
                AutoDataBindControl.EventDataBinding = field.GetValue(null);
            }
        }
        catch { }

        if (AutoDataBindControl.EventDataBinding == null)
        {
            // effectively disables the auto-binding feature
            AutoDataBindControl.EventDataBinding = new object();
        }
    }

    protected override void DataBind(bool raiseOnDataBinding)
    {
        base.DataBind(raiseOnDataBinding);

        // flag that databinding has taken place
        this.needsDataBinding = false;
    }

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);

        // check for the presence of DataBinding event handler
        if (this.HasEvents())
        {
            EventHandler handler = this.Events[AutoDataBindControl.EventDataBinding] as EventHandler;
            if (handler != null)
            {
                // flag that databinding is needed
                this.needsDataBinding = true;

                this.Page.PreRenderComplete += new EventHandler(this.OnPreRenderComplete);
            }
        }
    }

    void OnPreRenderComplete(object sender, EventArgs e)
    {
        // DataBind only if needed
        if (this.needsDataBinding)
        {
            this.DataBind();
        }
    }
}

如果未附加DataBinding事件处理程序,或者如果控件是手动绑定数据(直接或通过父级)的,则此解决方案将禁用自身。

请注意,此代码中的大多数仅是通过跳转来测试事件是否存在。 唯一需要的反思是一次性查找以获取用作EventDataBinding的键的object

ControlBuilder类上有一个internal ArrayList称为SubBuilders 对于每个数据绑定表达式TemplateParser参与者, ProcessCodeBlock()将具有BlockType属性CodeBlockType.DataBindingCodeBlockBuilder对象添加到SubBuilders

因此,如果可以获取所需的ControlBuilder的句柄,则应该能够反射性地遍历SubBuilders并查找CodeBlockBuilder类型的对象,其中BlockType == CodeBlockType.DataBinding

请注意,这当然令人讨厌,我真的很怀疑这是解决您的核心问题的最佳方法。 如果您退后两步并查看原始问题,则可以将其张贴在Stackoverflow上-有很多超级聪明的人可以帮助您找到一个好的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM