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.

War es hilfreich?

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top