11

そこで、これが私たちがやりたいことです: カスタム フレームで囲まれた汎用 Web パーツを用意し、その中に他の Web パーツ (フレームなし) を動的に読み込みます。これはまったく可能だと思いますか?Jan Tielens SmartPartに少し似ていますが、ASP.Net User Controls だけでなく、他の Web パーツ用です... ;)

編集:これができるようになりました。解決策は実際には非常に簡単でした。コードをチェックしてください:

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

それは簡単です... WebパーツをXmlなどとして保存するためにリフレクションも使用しますが、それは重要ではありません。

4

5 に答える 5

4

私はそうは思わない。しばらく前にこれを試しましたが、PageInitにWebPartZoneアイテムしか追加できないという不満がありました。「コンテナ」Webパーツを初期化するまでには、保持ページがすでに初期化されているため、ゾーンを追加するには遅すぎると思います。

于 2009-01-07T09:02:49.330 に答える
4
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」クラスも示していません。これは単なる Web パーツ構成用のコンテナーであり、一連のプロパティです。より詳細に議論したい 2 つの問題があります。

  1. parentWebPartGuid - これは、ホスティング Web パーツの Guid (UniqueId?) です。何らかの理由で、リフレクションを使用して "StorageKeyInternal" をこの値に設定する必要があります (これはプライベート プロパティです)。設定しなくても済む可能性がありますが、少なくとも大部分の Web パーツでは設定する必要がありました。

  2. config.Properties - これは設定値です (カスタム .xml ファイルで設定しますが、どこからでも自由に取得できます)。これは少し似ているかもしれません..

私たちのフレームワークでは、動的プロパティ値などもサポートしていますが、それはまた別の機会に... これがすべて意味をなして、誰かを助けることができることを願っています.

于 2009-02-12T14:14:42.293 に答える
2

これを行うには(少なくとも)2つの方法があります。iframeHTML要素を使用する方法と、JavaScript(おそらくAjaxを使用)によってコンテンツが変更されるdivのみを使用する方法です。

[注]私の答えは一般的です(つまり、Webデザイン側で)、あなたの技術的な文脈でそれがどのようになっているのかわかりません。したがって、この答えを削除する必要があるかもしれません...

于 2009-01-07T09:02:55.210 に答える
2

WebPartFactory クラスのソースを取得する機会はありませんか? それとも、それについてもう少し情報がありますか?おそらく疑似コード?カスタム Web パーツがギャラリーにある場合、RSSViewer と同じ方法で参照できますが正しいですか? あなたがここで行ったことをどのように実行すればよいのか、私にはよくわかりません。これを行う方法をよりよく理解したいと思います。

ありがとう!

于 2009-11-24T19:39:41.450 に答える
0

別のカスタム Web パーツ内でカスタム Web パーツをインスタンス化する場合は、.ascx で次のコードを使用します。

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

名前空間の値とアセンブリの値は、webconfig またはパッケージ ファイル ([マニフェスト] タブ) の 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);
于 2014-04-15T12:56:49.087 に答える