Wie zu erkennen, ob ASP.NET-Steuerelement Eigenschaften Databinding Ausdrücke enthalten?
-
06-07-2019 - |
Frage
Ich habe eine benutzerdefinierte Steuerung, die von System.Web.UI.Control
und einige seiner Eigenschaften erbt können deklarativ mit Datenbindung Ausdrücke eingestellt werden. z.
<foo:Foo runat="server" MyFoo="<%# this.GetFoo() %>" />
Nun, wenn ich tun, dass ich .DataBind()
über die Kontrolle (oder einer seiner Eltern) aufrufen müssen diese Ausdrücke zu bewerten.
Was würde ich zu tun, um der Lage sein mag, ist, erkennen , wenn alle Eigenschaften auf diese Weise eingestellt wurden und nur automatisch die benutzerdefinierte Kontrollanruf this.DataBind()
nach OnPreRender
haben oder dort zu.
Die Frage : Wie kann ich erkennen, ob Datenbindung Ausdrücke ausgeführt werden warten
Ich bin davon überzeugt, dass in einiger ControlBuilder
oder DataBindContext
Klasse der Informationen lebt, dies zu bestimmen benötigt. Ich habe mit Reflektor gejagt herum und kann nicht scheinen, um es zu finden.
soll ich hinzufügen, dass ich will nicht den Aufwand für die Ausführung DataBind()
zahlen, wenn keine direkte Eigenschaften auf diese Weise zugewiesen wurden. Aus diesem Grund möchte ich vor der Hand zu erkennen. Diese Klasse ist extrem leicht, aber ich würde die Fähigkeit gern deklarativ Eigenschaften festgelegt, ohne Code hinter zu benötigen.
Lösung
Doing einige tiefer Blick in ControlBuilder
, bemerkte ich, dass die kompilierte Fabrik für jede Steuerungsinstanz eine DataBinding
Event-Handler anhängen wird, wenn Daten sind verbindlich Ausdrücke vorhanden. Ich habe festgestellt, dass für diese Überprüfung scheint eine sehr zuverlässige Methode, um zu bestimmen, ob Datenbedarf verbindlich aufzutreten. Hier ist die Grundlage meiner Lösung für das Problem:
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();
}
}
}
Diese Lösung selbst deaktiviert, wenn kein DataBinding
Ereignishandler angebracht ist, oder wenn die Steuerung manuell Daten gebunden (direkt oder über einen Elternteil).
Beachten Sie, dass die meisten dieser Code springt nur durch Reifen für die Existenz des Ereignisses testen zu können. Die einzige Reflexion erforderlich ist eine einmalige Lookup die object
als Schlüssel für EventDataBinding
verwendet zu erhalten.
Andere Tipps
Es gibt eine internal ArrayList
SubBuilders
auf der ControlBuilder
Klasse. Für jeden Datenbindung Ausdruck TemplateParser
enocunters, fügt ProcessCodeBlock()
ein CodeBlockBuilder
Objekt mit einer BlockType
Eigenschaft CodeBlockType.DataBinding
SubBuilders
.
Wenn Sie also einen Griff in die ControlBuilder
bekommen Sie wollen, sollten Sie in der Lage sein, reflektiv über SubBuilders
iterieren und suchen Sie nach Objekten des Typs CodeBlockBuilder
wo BlockType == CodeBlockType.DataBinding
.
Hinweis natürlich ist dies alle Arten von bösen und ich bin wirklich verdächtig dies der beste Weg ist Ihr Kernproblem zu lösen. Wenn Sie zwei Schritte zurück und auf dem ursprünglichen Problem aussehen, vielleicht schreiben, dass auf Stackoverflow statt -. Es gibt viele hochintelligente Menschen, die mit einer guten Lösung kommen können helfen