オノデラの研究日記 in わんくま

思いついたネタを気ままに書いていくブログ

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  209  : 記事  5  : コメント  550  : トラックバック  40

ニュース

プロフィール

  • ●おのでら
    宮城県在住
    主に業務向けソフトを製作

Twitter

ニュース

主なリンク

XNA 関連リンク

アイテム

ゲーマーカード

その他

記事カテゴリ

書庫

日記カテゴリ

This article is the article which is being introduced in Japanese about a way of dynamic addition of web parts.

 Webパーツとは、ユーザーがWeb上でニュースやカレンダーなどの様々なパーツを自由にレイアウトできる仕組みで、Windows Live や My Yahoo! などのページを見ていただければイメージしやすいかと思います。Microsoft 製品ではポータルサイトの制作として SharePoint なんかが有名ですね。

 このWebパーツを使ったサイトの制作は ASP.NET(2.0) でも行うことができ、ツールボックスにはWebパーツ関連のコントロールがいくつか存在します。10個ちょっとしかありませんが、サーバーコントロールであればほとんどがWebパーツ化できるので意外といろんなものが作れたりします。

WebPartsコントロール

 作り方も非常に簡単で、コントロールを配置するだけでできてしまいます。「レイアウトの位置変更」や「最小化」「非表示」「名前変更」などは初めから備わっており、ユーザーごとにレイアウトの状態保存も自動的に行ってくれます(まあ実際に運用となるとそれなりに考慮しないといけない部分もありますが)。

Webパーツ

 で、やっと本題です(^^;)
 ユーザーが扱えるWebパーツはあらかじめ配置しておいたコントロールのみとなってしまいますが、場合によっては新しいコントロールを動的に追加したいこともあるかと思います。

 それを行うには下のようなコードを追加することで動的にWebパーツを追加することができます。下のコードではサーバーコントロールである TextBox を Webパーツでラップし、Webパーツゾーンに追加しています。(Webパーツはゾーンの上に配置する形になります。もちろん移動もです。)

protected void Page_Load(object sender, EventArgs e)
{
     TextBox textBox = new TextBox();
     textBox.ID = "addedTextBox";
     textBox.Attributes.Add("runat", "server");
     GenericWebPart gwp = this.WebPartManager1.CreateWebPart(textBox);
     gwp.Title = "追加したテキストボックス";
     this.WebPartManager1.AddWebPart(gwp, this.WebPartZone2, 0); }

Webパーツ動的追加

 しかし、実行してみるとわかりますが、ボタンなどを押してポストバックするたびにテキストボックスがどんどん追加されていってしまいます。これはWebパーツのレイアウト情報がポストバックするたびに保存されるため、Page_Load メソッドが呼ばれるたびにWebパーツを追加してしまうからです。

Webパーツが増殖

 なので普通は「IsPostBack」プロパティでポストバックの時はWebパーツ追加を実行しないようにします。

protected void Page_Load(object sender, EventArgs e)
{
     if (!this.IsPostBack)
     {
         TextBox textBox = new TextBox();
         textBox.ID = "addedTextBox";
         textBox.Attributes.Add("runat", "server");
         GenericWebPart gwp = this.WebPartManager1.CreateWebPart(textBox);
         gwp.Title = "追加したテキストボックス";
         this.WebPartManager1.AddWebPart(gwp, this.WebPartZone2, 0);
     } }

[注意]
 上を検証する前に以下のコードを実行して以前のWebパーツ情報を消してください。

for (int i = this.WebPartManager1.WebParts.Count - 1; i >= 0; i--)
{
     try
     {
         this.WebPartManager1.DeleteWebPart(this.WebPartManager1.WebParts[i]);
     }
     catch (Exception) {} }

※try-catch でスルーしているのは静的Webパーツが存在することを考慮して。


 で、こうすることによってページが開かれたときにだけWebパーツが追加されるようになるのですが、実は問題があり、一回ポストバックをかけるとなぜか追加したWebパーツが消えてしまいます。おそらく Page_Load メソッドで追加したWebパーツは WebPartManager が保存管理していないためではないかと思われます。ちなみにボタンイベントなどで追加した場合は正常に保存されるようです。

 この問題を解決するためにいろいろ探し回ったのですが、日本語のサイトでは見つけられず、英語圏の方でようやく見つけられました。

http://blogs.neudesic.com/blogs/david_barkol/archive/2006/02/10/45.aspx

 簡単に訳すと「追加した Webパーツをパーソナル化するために変更フラグを立てなければいけない」ということです。

 このフラグを立てるには「WebPartManager.SetPersonalizationDirty」というメソッドを呼ぶことにより設定できるのですが、実はこのメソッドは protected で宣言されており、そのままでは呼ぶことができません。上記リンクではこのクラスを派生させて呼び出すようにしています。

 まず、このクラスを派生させたクラスを作るのですが、サーバーコントロールは単純に継承したクラスのコードを記述してもそのままではページに配置できません。必ずクラスライブラリ専用のプロジェクトを作成し、そちらに記述する必要があります。

 ソリューションからプロジェクトを作成します。

新しいプロジェクト

 プロジェクトの名前は適当です。

 クラスライブラリ

 System.Web の参照を追加しましょう。

System.Web

 WebPartManager の派生クラスを作ります。今回クラス名は「WebPartManagerEx」としておきます。コードは下のようにして基本クラスの「SetPersonalizationDirty」メソッドを呼べるようにします。

using System;
using System.Data;
using System.ComponentModel;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

namespace ClassLibrary1
{
     ///
     /// WebPartManagerEx の概要の説明です
     ///
    [ToolboxData("<{0}:WebPartManagerEx runat=server>")]
     public class WebPartManagerEx : WebPartManager
     {
         ///
         /// System.Web.UI.WebControls.WebParts.WebPartManager コントロールのカスタムの
         /// パーソナル化データが変更されたことを示すフラグを設定します
         ///
         public new void SetPersonalizationDirty()
         {
             base.SetPersonalizationDirty();
         }
     } }

 クラスを作成したらページに貼り付けます。前の WebPartManager は消すなり何なりしてください。

WebPartManagerEx

 あとはプログラムで Webパーツを追加した後にこのメソッドを呼び出せばOKです。

protected void Page_Load(object sender, EventArgs e)
{
     if (!this.IsPostBack)
     {
         TextBox textBox = new TextBox();
         textBox.ID = "addedTextBox";
         textBox.Attributes.Add("runat", "server");
         GenericWebPart gwp = this.WebPartManagerEx1.CreateWebPart(textBox);
         gwp.Title = "追加したテキストボックス";
         this.WebPartManagerEx1.AddWebPart(gwp, this.WebPartZone2, 0);
         this.WebPartManagerEx1.SetPersonalizationDirty();
     } }

 まあ、これが正当なやりかたなのかどうかはわかりませんが、こういうやり方もあるんだ程度に知っておいていただければと思います。

 

 ちなみにこの Webパーツをうまく使えば下のようなポータルサイトを作ることだってできます。視覚的にレイアウトの調整ができるのでウマー(゚Д゚)です。

わんくまポータルサイト

投稿日時 : 2007年9月21日 22:55

コメント

No comments posted yet.

Post Feedback

タイトル
名前
Url:
コメント