C# 如何检测ASP.NET控件属性是否包含数据绑定表达式?
我有一个自定义控件,它继承自C# 如何检测ASP.NET控件属性是否包含数据绑定表达式?,c#,asp.net,data-binding,custom-controls,C#,Asp.net,Data Binding,Custom Controls,我有一个自定义控件,它继承自System.Web.UI.control,它的一些属性可以使用数据绑定表达式进行声明性设置。e、 g <foo:Foo runat="server" MyFoo="<%# this.GetFoo() %>" /> 现在,当我这样做时,我需要调用控件(或其父控件之一)上的.DataBind(),以计算这些表达式 我想能够做的是检测是否有任何属性是以这种方式设置的,然后在OnPreRender之后自动调用自定义控件this.DataBind
System.Web.UI.control
,它的一些属性可以使用数据绑定表达式进行声明性设置。e、 g
<foo:Foo runat="server" MyFoo="<%# this.GetFoo() %>" />
现在,当我这样做时,我需要调用控件(或其父控件之一)上的.DataBind()
,以计算这些表达式
我想能够做的是检测是否有任何属性是以这种方式设置的,然后在OnPreRender
之后自动调用自定义控件this.DataBind()
,或者在那里
那么问题就来了:如何检测数据绑定表达式是否正在等待执行
我确信在一些ControlBuilder
或DataBindContext
类中,存在着确定这一点所需的信息。我用反射器四处搜寻,似乎找不到它
我应该补充一点,如果没有以这种方式分配直接属性,我不想支付执行
DataBind()
的开销。这就是为什么我想在手之前检测。这个类非常轻,但我希望能够声明性地设置属性,而不需要任何代码。在ControlBuilder
类上有一个名为SubBuilders
的内部数组列表。对于每个数据绑定表达式TemplateParser
enocunters,ProcessCodeBlock()
添加一个CodeBlockBuilder
对象,该对象具有BlockType
属性CodeBlockType.databinding
到SubBuilder
因此,如果您可以获得所需的ControlBuilder
的句柄,您应该能够反射式地迭代子生成器
,并查找类型为CodeBlockBuilder
的对象,其中BlockType==CodeBlockType.DataBinding
请注意,这当然是各种令人讨厌的,我真的怀疑这是解决你核心问题的最好方法。如果你后退两步,看看原来的问题,也许可以把它贴在Stackoverflow上——有很多超级聪明的人可以帮助你想出一个好的解决方案。深入了解ControlBuilder
,我注意到,当存在数据绑定表达式时,每个控件实例的编译工厂将附加一个数据绑定
事件处理程序。我发现,检查这一点似乎是确定是否需要进行数据绑定的一种非常可靠的方法。以下是我解决问题的基础:
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();
}
}
}
如果未连接数据绑定
事件处理程序,或者控件手动绑定数据(直接或通过父控件),则此解决方案将禁用自身
请注意,这段代码中的大部分只是为了能够测试事件的存在而跳转。唯一需要的反射是一次性查找,以获取用作事件数据绑定的键的对象
为什么不在代码隐藏中简单地按Page.DataBind()进行绑定?!它将绑定该页面中的所有控件,而不重新标记它们是什么。。。请看:正如我在问题中所说的,如果不需要,我不想支付执行DataBind()的开销。这就是最初的问题:有时会出现数据绑定表达式,如果不必添加代码,我希望不必在后面添加代码,这意味着控件本身应该调用DataBind
,我不想让性能损失总是DataBind
ing。我正在浏览System.Web.UI.WebControls.BaseDataBoundControl
是如何知道自动绑定的,但我认为它的方式对于这个简单的需求来说太笨重了。我想要实际的绑定信息,而不是像他们那样跟踪。听起来实际的信息可能会更昂贵(反射),但我会先检查一下。谢谢