Можно ли загрузить веб-часть внутри другой?

StackOverflow https://stackoverflow.com/questions/419632

  •  03-07-2019
  •  | 
  •  

Вопрос

Итак, это то, что мы хотим сделать:Мы хотим иметь общую веб-часть с пользовательским фреймом вокруг нее, а затем динамически загружать в нее другие веб-части (без фреймов).Как вы думаете, возможно ли это вообще?Немного похоже Умная деталь Яна Тиленса, только не для ASP.Net Пользовательских элементов управления, а для других веб-частей...;)

Редактировать:Теперь мы смогли это сделать.Решение на самом деле было довольно простым.Ознакомьтесь с кодом:

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

Вот так просто...Мы также используем отражение для хранения веб-частей в формате Xml и т.д., но это не относится к делу.

Это было полезно?

Решение 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);
    } 
}

Этот код нуждается в пояснении ... Пожалуйста, извините, если он не компилируется, мне пришлось удалить немало оригинального кода, это было очень специфично для реализации. Я не показывал " config " либо класс, это просто контейнер для настройки веб-частей, просто набор свойств. Есть 2 вопроса, которые я хотел бы обсудить более подробно:

<Ол>
  • parentWebPartGuid - это Guid (уникальный идентификатор?) веб-части хостинга. По какой-то причине мы должны установить " StorageKeyInternal " к этому значению, используя отражение (это частная собственность). Вы можете обойтись без настройки, но, по крайней мере, для большинства веб-частей мы должны были установить его.

  • config.Properties - это значения конфигурации (мы устанавливаем их в настраиваемом XML-файле, но вы можете получить его из любого места). Это может выглядеть как этот ..

  • В нашем фреймворке мы также поддерживаем такие вещи, как значения динамических свойств и т. д., но это на другой день ... Надеюсь, все это имеет смысл и может кому-нибудь помочь.

    Другие советы

    Я так не думаю. Я пытался это сделать некоторое время назад, и он жаловался только на то, что мог добавлять элементы WebPartZone в Page Init. Я думаю, что к моменту инициализации вашего "контейнера" WebPart слишком поздно, чтобы добавить больше зон, поскольку удерживающая страница уже инициализирована.

    Для этого есть (как минимум) два способа: использовать элемент iframe HTML или просто div, содержимое которого изменяется с помощью JavaScript (возможно, с помощью Ajax).

    [ПРИМЕЧАНИЕ] Мой ответ носит общий характер (т. е. на стороне веб-дизайна), я понятия не имею, как он в вашем техническом контексте, поэтому, возможно, мне следует удалить этот ответ ...

    Нет ли шансов получить исходный код для класса WebPartFactory?Или, может быть, немного больше информации об этом?Может быть, псевдокод?Если пользовательская веб-часть находится в галерее, на нее можно ссылаться таким же образом, как правильно RSSViewer?Я просто не совсем уверен, как приступить к выполнению того, что вы здесь сделали, и мне бы очень хотелось лучше понять, как это сделать.

    Спасибо!

    Когда я хочу создать пользовательскую веб-часть внутри другой пользовательской веб-части, я использую следующий код в .ascx

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

    Значение пространства имен и значение Assembly можно скопировать из строки SafeControls из веб-конфигурации или из файла пакета (на вкладке манифеста):)

    Когда я хочу создать его экземпляр, на самом деле динамия - это использовать следующий код в .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);
    
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top