Domanda

Quindi, questo è ciò che vogliamo fare: vogliamo avere una web part generica con un frame personalizzato attorno ad essa e quindi caricare dinamicamente altre web part (senza cornice) al suo interno. Questo sarebbe possibile, pensi? Un po 'come Jan Tielens SmartPart , non solo per i controlli utente ASP.Net, ma per altre web part. .;)

Modifica: siamo stati in grado di farlo ora. La soluzione era in realtà piuttosto semplice. Controlla il codice:

public class WebPartWrapper : System.Web.UI.WebControls.WebParts.WebPart {
    protected override void CreateChildControls() {    
        Panel pnl = new Panel();
        this.Controls.Add(pnl);
        WebPart dynamicPart = WebPartFactory.CreateWebPart("RSSViewer");
        pnl.Controls.Add(dynamicPart);
    }
}

Facile come quello ... Usiamo anche reflection per memorizzare le webpart come Xml ecc., ma questo è il punto.

È stato utile?

Soluzione 2

public class WebPartWrapper : System.Web.UI.WebControls.WebParts.WebPart {
    protected override void CreateChildControls() {    
        Panel pnl = new Panel();
        this.Controls.Add(pnl);
        var factory = new WebPartFactory()
        WebPart dynamicPart = factory.CreateWebPart("RSSViewer", this.Guid);
        pnl.Controls.Add(dynamicPart);
    }
}

public class WebPartFactory {
    public WebPart CreateWebpart(string webpartName, Guid parentWebPartGuid)
    {
        var config = ConfigurationFactory.LoadConfiguration(webpartName);

        Assembly webPartAssembly = Assembly.Load(config.Assembly);
        Type webPartType = webPartAssembly.GetType(config.Class);
        object actualWebPart = Activator.CreateInstance(webPartType);

        foreach (var item in config.Properties)
        {
            PropertyInfo webPartProperty = webPartType.GetProperty(item.Name);
            object webPartPropertyValue = Convert.ChangeType(itemValue, Type.GetType(item.Type));
            if (!String.IsNullOrEmpty(item.Value))
                webPartProperty.SetValue(actualWebPart, webPartPropertyValue, null);
        }

        RunMethod("set_StorageKeyInternal", actualWebPart, new object[] { parentWebPartGuid });
        return actualWebPart as WebPart;
    }

    private void RunMethod(string methodName, object objectInstance, object[] methodParameters)
    {
        BindingFlags flags = BindingFlags.Instance | BindingFlags.Public |
            BindingFlags.NonPublic;

        Type t = objectInstance.GetType();
        MethodInfo m = GetMethod(t, methodName, flags);
        if (m != null)
        {
            m.Invoke(objectInstance, methodParameters);
        }
    }

    private MethodInfo GetMethod(Type instanceType, string methodName, BindingFlags flags)
    {
        MethodInfo m = instanceType.GetMethod(methodName, flags);
        if (m != null)
        {
            return m;
        }

        if (instanceType.GetType() == typeof(object) || instanceType.BaseType == null)
        {
            return null;
        }

        return GetMethod(instanceType.BaseType, methodName, flags);
    } 
}

Questo codice ha bisogno di spiegazioni ... Per favore, mi scusi se non viene compilato, ho dovuto rimuovere un bel po 'di codice originale, era roba molto specifica per l'implementazione. Non ho mostrato la "quotazione" " sia di classe, è solo un contenitore per la configurazione di webpart, solo un mucchio di proprietà. Ci sono 2 problemi che vorrei discutere in modo più dettagliato:

  1. parentWebPartGuid - Questo è il Guid (UniqueId?) della webpart di hosting. Per qualche motivo, dobbiamo impostare " StorageKeyInternal " a questo valore, usando reflection (è una proprietà privata). Probabilmente puoi evitare di non impostarlo, ma almeno per la maggior parte delle webpart abbiamo dovuto impostarlo.

  2. config.Properties - Questi sono i valori di configurazione (li impostiamo in un file .xml personalizzato, ma sentiti libero di ottenerlo da qualsiasi luogo). Può sembrare un po ' this ..

Nel nostro framework supportiamo anche cose come valori di proprietà dinamiche ecc., ma è per un altro giorno ... Spero che tutto ciò abbia senso e possa aiutare qualcuno.

Altri suggerimenti

Non credo. Ci ho provato un po 'di tempo fa e mi sono lamentato solo di poter aggiungere elementi WebPartZone in Page Init. Penso che quando arriva l'inizializzazione del tuo "contenitore" WebPart è troppo tardi per aggiungere più zone poiché la pagina di attesa è già stata inizializzata.

Esistono (almeno) due modi per farlo: usare l'elemento HTML iframe o solo un div il cui contenuto viene modificato da JavaScript (probabilmente con Ajax).

[NOTA] La mia risposta è generica (es. sul lato del Web design), non ho idea di come sia nel tuo contesto tecnico, quindi forse dovrei eliminare questa risposta ...

Non c'è possibilità di ottenere l'origine per la classe WebPartFactory? O forse un po 'più di informazioni al riguardo? Pseudo codice forse? Se nella web è presente una web part personalizzata, è possibile fare riferimento nello stesso modo in cui RSSViewer è corretto? Non sono proprio sicuro di come fare ciò che hai fatto qui, e mi piacerebbe molto capire meglio come farlo.

Grazie!

Quando voglio creare un'istanza di una web part personalizzata all'interno di un'altra web part personalizzata, utilizzo il seguente codice in .ascx

<%@ Register tagPrefix="uc1" Namespace="Megawork.Votorantim.Intranet.Webparts_Intranet.LikeButton" Assembly="Megawork.Votorantim.Intranet, Version=1.0.0.0, Culture=neutral, PublicKeyToken=769156d154035602"  %>

Il valore dello spazio dei nomi e il valore dell'Assemblea possono essere copiati dalla riga SafeControls dal webconfig o dal file del pacchetto (nella scheda manifest) :)

Quando voglio istanziarlo dinamicamente (in effetti) è usare il seguente codice in .cs

//This is the namespace of the control that will be instantiated dinamically    
string type = "My.Custom.Namespace.WebpartToBeAdded.WebpartToBeAdded";

// Instantiate the control dinamically based on his type
System.Web.UI.WebControls.WebParts.WebPart genericWP = (System.Web.UI.WebControls.WebParts.WebPart)Activator.CreateInstance(Type.GetType(type));

// sets the page to the genericWP (i dont know if this is required)
genericWP.Page = this.Page;

// Note: if you want to call custom methods of the dinamically instantiated controls (like a custom load method) you will need to create an interface and make your dinamically instantiated webpart implement it. You will need to do it in that file that have the following code: private const string _ascxPath @"~/_CONTROLTEMPLATES/...". Then you can do the following
//IMyInterface ig = (IMyInterface)genericWP;
//ig.MyCustomLoadMethod(someParam);

// Adds the controls to a container, an asp panel by example.
panelDinamicControls.Controls.Add(genericWP);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top