Pergunta

Então, isso é o que queremos fazer: Nós queremos ter uma parte web genérico com a custom frame em torno dele e, em seguida, carregar dinamicamente outras partes da web (sem moldura) dentro dela. Será que isso em tudo ser possível que você acha? Um pouco como Jan Tielens SmartPart , não só para ASP.NET controles de usuário, mas para outras partes da Web .. .;)

Edit: Nós temos sido capazes de fazer isso agora. A solução foi realmente muito simples. Confira o código:

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);
    }
}

Fácil assim ... Nós também usar o reflexo para armazenar os webparts como XML etc., mas isso é irrelevante.

Foi útil?

Solução 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);
    } 
}

Este código tem algumas explicações ... Por favor, desculpe-me se ele não compilar, eu tinha que remover um pouco de código original, era muito material específico implementação. Eu não tenho mostrado a classe "config" quer, é apenas um recipiente para a configuração de webparts, apenas um monte de propriedades. Há 2 questões que eu gostaria de discutir com mais detalhes:

  1. parentWebPartGuid - Este é o Guid do webpart hospedagem (UniqueId?). Por alguma razão nós temos que definir "StorageKeyInternal" a este valor, usando a reflexão (é uma propriedade privada). Você pode, possivelmente, obter afastado com não defini-lo, mas pelo menos para a maioria dos webparts tivemos para defini-lo.

  2. config.Properties - Este é os valores de configuração (que colocá-las em um arquivo .xml personalizado, mas fique à vontade para obter isso de qualquer lugar). Pode parecer um pouco como este ..

No nosso quadro temos coisas também apoio como valores de propriedade dinâmica etc., mas isso é para outro dia ... Espero que isso tudo faz sentido e pode ajudar alguém.

Outras dicas

Eu não penso assim. Tentei fazer isso um tempo atrás e ele reclamou apenas ser capaz de adicionar itens WebPartZone na página Init. Eu acho que no momento em que começar de para inicializar o seu "container" WebPart que seja tarde demais para adicionar mais zonas como a página de realização já foi iniciado.

Há (pelo menos) duas maneiras de fazer isso:. Utilizando elemento iframe HTML, ou apenas um div cujo conteúdo é alterado pelo JavaScript (provavelmente com o Ajax)

[NOTA] A minha resposta é genérica (ie. No lado Web design), eu não tenho nenhuma idéia de como ele em seu contexto técnico, então talvez eu deveria excluir esta resposta ...

Sem chance em obter a fonte para a classe WebPartFactory está lá? Ou talvez um pouco mais informações sobre isso? pseudo-código, talvez? Se uma peça personalizada web está na galeria poderia ser referenciado da mesma forma como RSSViewer é correto? Estou realmente não sei como ir sobre fazer o que você fez aqui, e eu gostaria muito de entender melhor como fazer isso.

Obrigado!

Quando um quer instanciar um webpart personalizado dentro de outro costume Webpart eu uso o seguinte código no .ascx

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

O valor Namespace eo valor Assembleia podem ser copiados a partir da linha SafeControls do webconfig ou a partir do arquivo de pacote (em guia manifesto):)

Quando eu quero instanciar que dinammicaly (na verdade) é usar o seguinte código nos 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);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top