簡體   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