モバイル アダプターを作成する
最終更新日: 2011年3月17日
適用対象: SharePoint Foundation 2010
ここでは、Microsoft SharePoint Foundation ページの Web パーツがモバイル デバイスにアクセスできるようにするモバイル アダプター クラスの作成方法について説明します。
Web パーツを適合させる具体的な例については、「[ウォークスルー] モバイル アダプターを作成する」を参照してください。
開発環境を設定する
- SharePoint Foundation を使用して、モバイル開発用の開発環境を整えます。詳細については、「SharePoint へのモバイル デバイス アクセスの開発を準備する」とその子トピックを参照してください。
前提条件の開発タスク
モバイル デバイスへのアクセスを可能にする Web パーツ ページが存在しない場合は、作成する必要があります。詳細については、「SharePoint Foundation の Web パーツ インフラストラクチャ」および「WebPartPage」を参照してください。
注意
WebPartMobilePage クラスのページは作成しません。これらは、モバイル デバイスが Web パーツ ページ (WebPartPage) を要求するとき、ランタイムによって作成されます。
モバイル アクセス用に適合させる Web パーツが存在しない場合は、作成する必要があります。詳細については、「SharePoint Foundation の Web パーツ インフラストラクチャ」と「Web Parts Overview」を参照してください。
モバイル アダプター クラスを作成し展開する
Visual Studio クラス ライブラリ プロジェクトで、System.Web と Microsoft.SharePoint.dll への参照情報を追加し、次に名前空間 Microsoft.SharePoint.WebPartPages に対して using (Visual Basic では Imports) ステートメントを追加します。アダプター実装の詳細によっては、他の名前空間に対して using ステートの追加が必要になる場合があります。一般的にモバイル アダプターは、System.Web.UI.MobileControls、Microsoft.SharePoint、および Microsoft.SharePoint.MobileControls 内の型の呼び出しを行います。
Web パーツ クラス MobileAdapter というクラスを追加します。Web パーツ クラスは、適合させる Web パーツの名前です。たとえば Web パーツが StockListWebPart の場合、アダプター クラスに StockListWebPartMobileAdapter という名前を付けます。次に WebPartMobileAdapter から継承するように設定します。
「Namespace Naming Guidelines (英語)」のガイドラインに準拠するように、名前空間を設定します。モバイル アダプターの場合は、自分の会社.SharePoint.WebPartPages.MobileAdapters のような名前を使用します。
WebPartMobileAdapter.Control プロパティには、virtual や override (Visual Basic では Overridable と Overrides) のマークは付けらませんが、非表示や置換によって、プロパティを効果的にオーバーライドしなければならない場合があります。オーバーライドするには、new キーワード (Visual Basic では Shadows) を使用して、派生クラスで新しい Control クラスを宣言します。オーバーライドする理由およびその方法については、「WebPartMobileAdapter.Control」の参照トピックを参照してください。
既定の実装が Web パーツへのモバイル アクセスに適応しない場合は、CreateControlsForSummaryView() メソッドを上書きします。基本的にオーバーライドによって必要な子コントロールが作成され、モバイル デバイスに表示される順番で Controls コレクションに追加されます。通常、少なくとも Web パーツ用の小さいアイコンとタイトルをモバイル デバイスの概要ビューに表示させたいと考えます (概要ビューに表示させたいものが小さいアイコンとタイトルだけの場合は、CreateControlsForSummaryView() をオーバーライドする必要がありません)。これを簡単に行えるように、2 つのヘルパー メソッド (CreateWebPartIcon(WebPartMobileAdapter.WebPartIconLink) と CreateWebPartLabel()) が提供されています。
しかし概要ビューでも、詳細な情報が必要になる場合があります。たとえば、適合対象の Web パーツにすべて同じ種類の複数の子アイテムがあるとします。Label コントロールを使用して、概要ビューのアイコンとタイトルの後に子の合計数を追加できます。以下のコードでその方法を説明します。
重要 この例では、2 つの前提があります。1 つ目の前提は、適合対象の Web パーツに、String 型の Count プロパティがあり、子アイテムの合計数を返すこと。2 つ目の前提は、このプロパティがアクセス可能なこと。これは、前の手順で示唆したように、Control プロパティが非表示になり置換されているためです。
protected override void CreateControlsForSummaryView() { Image iconImage = this.CreateWebPartIcon(WebPartIconLink.LinkToDetailView); iconImage.BreakAfter = false; this.Controls.Add(iconImage); Label titleLabel = this.CreateWebPartLabel(); titleLabel.BreakAfter = false; this.Controls.Add(titleLabel); Label count = new Label() { Text=this.Control.Count.ToString() } this.Controls.Add(count); }
Protected Overrides Sub CreateControlsForSummaryView() Dim iconImage As Image = Me.CreateWebPartIcon(WebPartIconLink.LinkToDetailView) iconImage.BreakAfter = False Me.Controls.Add(iconImage) Dim titleLabel As Label = Me.CreateWebPartLabel() titleLabel.BreakAfter = False Me.Controls.Add(titleLabel) Dim count As New Label() With {.Text=Me.Control.Count.ToString()} Me.Controls.Add(count) End Sub
この例のように、CreateWebPartIcon(WebPartMobileAdapter.WebPartIconLink) メソッドに LinkToDetailView が渡され、デバイスのブラウザーが CSS と ECMAScript 1.0 以降をサポートしている場合は、SharePoint Foundation Mobile Adapter Framework の展開スクリプトを実行する、クリック可能なコントロールとして機能する方向アイコンがレンダリングされます。ユーザーがクリックすると、Web パーツは詳細ビューに展開され、アイコンが下方向キーに変わります (下方向キー自体が折りたたみスクリプトを実行するコントロールです)。ブラウザーが CSS と ECMAScript 1.0 以降の両方をサポートしていない場合は、別のアイコンがレンダリングされ、そのアイコンをクリックすると、Web パーツの詳細ビューで構成されるページ (mblwpdetail.aspx) に移動します。モバイル ページ上の Web パーツに詳細ビューを表示しない場合は、NoLink を CreateWebPartIcon(WebPartMobileAdapter.WebPartIconLink) に渡します。
CreateControlsForSummaryView() のオーバーライドでは、他に次のようなことを行います。
レンダリング ロジックで、特定のエンティティが null でないことや、他の条件が真であることを前提としている場合、前提をテストするオーバーライドを設計することや、条件が真でないときに何もしないか代わりのレンダリングを提供することを検討します。たとえば、適合する Web パーツがリスト ビューをレンダリングする場合は、this.Control.View.MobileView をテストして、ビューがモバイル ビューとして指定されているかどうかを確認できます。詳細については、「MobileView」を参照してください。
適合させようとしている Web パーツの表示内容がアイコンとタイトルだけで伝わらない場合は、概要ビュー用に小さい表示部分を構築することを検討してください。たとえば円グラフが Web パーツの一部の場合、CreateControlsForSummaryView() のオーバーライドには、円グラフの小さいストック イメージを含めることができます。Web パーツに写真が含まれる場合は、オーバーライドには非常に小さく縮小されたイメージを含めることができます。
既定の実装が Web パーツへのモバイル アクセスに適応していない場合は、CreateControlsForDetailView() をオーバーライドします。既定の実装は、Web パーツ用のアイコンとタイトルの後に、Web パーツ用の詳細ビューがないことを示すメッセージをレンダリングします。CreateControlsForSummaryView() をオーバーライドし、詳細ビューを表示しない場合は、CreateControlsForDetailView() をオーバーライドして、以下の例に示すように何も実行させないようにします。
protected override void CreateControlsForDetailView(){}
Protected Overrides Sub CreateControlsForDetailView() End Sub
詳細ビューが必要な場合、CreateControlsForDetailView() をオーバーライドするプロセスは、Web パーツをより詳細に表示するという点を除けば、CreateControlsForSummaryView() をオーバーライドするプロセスと同じです。たとえば Web パーツに同じ種類の子アイテムが複数存在する場合、最初のいくつかを詳細ビューに表示することを検討します。以下のサンプル コードでは、CreateControlsForDetailView() メソッドがオーバーライドされ、現リストのアイテムが最大 3 つまで子アイテムとして Web パーツ アイコンとタイトル下に表示されます。このコードの詳細については、「[ウォークスルー] モバイル アダプターを作成する」を参照してください。
protected override void CreateControlsForDetailView() { Image iconImage = this.CreateWebPartIcon(WebPartIconLink.LinkToSummaryView); iconImage.BreakAfter = false; this.Controls.Add(iconImage); Label titleLabel = this.CreateWebPartLabel(); this.Controls.Add(titleLabel); SPSite siteCollection = SPContext.Current.Site; SPUser currentUser = SPContext.Current.Web.CurrentUser; SPList taskList = siteCollection.AllWebs["MyGPSite"].Lists["Tasks"]; SPListItemCollection allTasks = taskList.GetItems(taskList.DefaultView); // Use LINQ to filter out other users ... var lightweightTasksOfUser = from SPListItem task in allTasks where task["AssignedTo"].ToString().EndsWith(currentUser.Name) select new {task.Title, Priority=task["Priority"]}; // ... and unneeded columns. Int16 itemCount = 1; foreach (var lightweightTask in lightweightTasksOfUser) { Image taskIcon = new Image() { ImageUrl = this.ItemBulletIconUrl, BreakAfter = false}; this.Controls.Add(taskIcon); Label taskTitle = new Label { Text = lightweightTask.Title, BreakAfter = false}; taskTitle.Font.Bold = BooleanOption.True; this.Controls.Add(taskTitle); Label priority = new Label() { Text = " " + lightweightTask.Priority }; priority.Font.Size = FontSize.Small; this.Controls.Add(priority); this.Controls.Add(new LiteralText()); // Render no more than 3 tasks, but provide link to others. if (itemCount++ >= 3) { Link moreItemLink = new Link { Text = "All my tasks", href = SPMobileUtility.GetViewUrl(taskList, taskList.Views["My Tasks"]) }; this.Controls.Add(moreItemLink); break; } // end "if limit has been reached" } // end "for each lightweight task of the current user" } // end CreateControlsForDetailView
Protected Overrides Sub CreateControlsForDetailView() Dim iconImage As Image = Me.CreateWebPartIcon(WebPartIconLink.LinkToSummaryView) iconImage.BreakAfter = False Me.Controls.Add(iconImage) Dim titleLabel As Label = Me.CreateWebPartLabel() Me.Controls.Add(titleLabel) Dim siteCollection As SPSite = SPContext.Current.Site Dim currentUser As SPUser = SPContext.Current.Web.CurrentUser Dim taskList As SPList = siteCollection.AllWebs("MyGPSite").Lists("Tasks") Dim allTasks As SPListItemCollection = taskList.GetItems(taskList.DefaultView) ' Use LINQ to filter out other users ... Dim lightweightTasksOfUser = From task As SPListItem In allTasks Where task("AssignedTo").ToString().EndsWith(currentUser.Name) Select New With {Key task.Title, Key .Priority = task("Priority")} '... and unneeded columns. Dim itemCount As Int16 = 1 For Each lightweightTask In lightweightTasksOfUser Dim taskIcon As New Image() With {.ImageUrl = Me.ItemBulletIconUrl, .BreakAfter = False} Me.Controls.Add(taskIcon) Dim taskTitle As Label = New Label With {.Text = lightweightTask.Title, .BreakAfter = False} taskTitle.Font.Bold = BooleanOption.True Me.Controls.Add(taskTitle) Dim priority As New Label() With {.Text = " " & lightweightTask.Priority} priority.Font.Size = FontSize.Small Me.Controls.Add(priority) Me.Controls.Add(New LiteralText()) ' Render no more than 3 tasks, but provide link to others. If itemCount >= 3 Then itemCount += 1 Dim moreItemLink As Link = New Link With {.Text = "All my tasks", .href = SPMobileUtility.GetViewUrl(taskList, taskList.Views("My Tasks"))} Me.Controls.Add(moreItemLink) Exit For End If ' end "if limit has been reached" itemCount += 1 Next ' end "for each lightweight task of the current user" End Sub ' end CreateControlsForDetailView
Init イベント、Load イベント、PreRender イベント、または Unload イベント中にカスタム ロジックが必要な場合は、それぞれ OnLoadForMobile(EventArgs) メソッド、OnInitForMobile(EventArgs) メソッド、OnPreRenderForMobile(EventArgs) メソッド、OnUnloadForMobile(EventArgs) メソッドをオーバーライドします。
モバイル ユーザーを、組み込みの既定ページによって提供されたページではなく、カスタムの概要ビュー ページまたは詳細ビュー ページにリダイレクトする場合は、SummaryViewPageUrl プロパティ、または DetailViewPageUrl プロパティをオーバーライドします。
Web パーツ タイトルの横に表示されるアイコンを変更するには、以下のプロパティの 1 つ以上をオーバーライドします。
SummaryViewTitleIconUrl – Web パーツが折りたたまれたときに、タイトルの横に表示されるアイコン。
DetailViewTitleIconUrl – Web パーツが展開されたときに、タイトルの横に表示されるアイコン。
TitleIconUrl – モバイル デバイスが展開/折りたたみスクリプトをサポートしない場合に、タイトルの横に表示されるアイコン。
以下のコードは、これらのプロパティの 1 つをオーバーラードする例を示しています。TitleIconUrl のオーバーライドでは、Web パーツがリストを表示し、そのリストに ImageUrl プロパティ内の独自のアイコンがある場合は、そのアイコンが表示されます。
protected override string TitleIconUrl { get { SPContext context = SPContext.GetContext(HttpContext.Current); if (String.IsNullOrEmpty(context.List.ImageUrl)) { return base.TitleIconUrl; } return context.List.ImageUrl; } }
Protected Overrides ReadOnly Property TitleIconUrl() As String Get Dim context As SPContext = SPContext.GetContext(HttpContext.Current) If String.IsNullOrEmpty(context.List.ImageUrl) Then Return MyBase.TitleIconUrl End If Return context.List.ImageUrl End Get End Property
アセンブリをコンパイルし、それに厳密な名前を付けて、ファーム内のすべてのフロントエンド Web サーバー上にあるグローバル アセンブリ キャッシュ (GAC) または Web アプリケーションの \BIN フォルダーに展開します。SharePoint Foundation ソリューションでアダプターを展開することによって、この作業を完了することをお勧めします。簡単にするために、このトピックでは GAC に展開すると想定します。選択肢の詳細については、「Bin またはグローバル アセンブリ キャッシュへのアセンブリの配置」を参照してください。アセンブリを開発コンピューターの GAC のみにコピーするには、gacutil.exe ユーティリティを使用します。新しいバージョンのアダプターが GAC にインストールされていることを確認する最も簡単な方法は、Visual Studio のビルド後イベントで起動するバッチ ファイルからユーティリティを実行することです。バッチ ファイルには以下の行があります。AssemblyNameは、コンパイルしたアセンブリの名前で置き換えます。
注意
このコードは、「[方法] ツールの場所を PATH 環境変数に追加する」の推奨事項に従っていることを前提としています。
gacutil –if bin\debug\AssemblyName.dll
compat.browser ファイルを編集する
テキスト エディターで \\Inetpub\wwwroot\wss\VirtualDirectories\port_number\App_Browsers\compat.browser ファイルを開き、refID 属性値 "default" を含む <browser> 要素までスクロールします。port_number は Web アプリケーションのポートです。<browser> 要素には、以下のような <controlAdapters> 子要素があります。
<controlAdapters> <adapter controlType="Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" adapterType="Microsoft.SharePoint.WebPartPages.XsltListViewWebPartMobileAdapter, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" /> <adapter controlType="Microsoft.SharePoint.WebPartPages.ListViewWebPart, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" adapterType="Microsoft.SharePoint.WebPartPages.ListViewWebPartMobileAdapter, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" /> <adapter controlType="Microsoft.SharePoint.Applications.GroupBoard.WebPartPages.WhereaboutsWebPart, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" adapterType="Microsoft.SharePoint.WebPartPages.WhereaboutsWebPartMobileAdapter, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" /> <adapter controlType="Microsoft.SharePoint.WebPartPages.ImageWebPart, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" adapterType="Microsoft.SharePoint.WebPartPages.ImageWebPartMobileAdapter, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" /> </controlAdapters>
上記の例のように、<adapter> 要素を <controlAdapters> 要素の子として追加し、適合させる Web パーツにアダプター クラスをマップします。controlType 属性と adapterType 属性は必須であることに注意してください。どちらもクラスの完全修飾名とアセンブリの 4 つの部分で構成される名前です。アダプターのアセンブリの公開キー トークンを取得するには、Visual Studio の [ツール] メニューの [アセンブリの公開キーを取得] アイテムを使用します (アイテムがない場合は、「[方法] アセンブリの公開キーを取得するツールを作成する」を参照してください)。この XML マークアップの詳細については、「ブラウザー定義ファイルのスキーマ (browsers 要素)」を参照してください。
以下は新しい <adapter> 要素の例です。1 番目は、SharePoint Foundation に付属の UserTasksWebPart を適合させる Contoso コントロール用です。2 番目は、同じ Northwinds ソリューションの Northwinds Web パーツを適合させる Northwinds コントロール用です。
<adapter controlType="Microsoft.SharePoint.WebPartPages.UserTasksWebPart, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c " adapterType="Contoso.SharePoint.WebPartPages.UserTasksWebPartMobileAdapter, Contoso, Version=1.0.0.0, Culture=neutral, PublicKeyToken=eedb3d3ba3b4c675" /> <adapter controlType="NorthWinds.SharePoint.WebPartPages.VotingWebPart, Northwinds, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ffec2e2af2b4c675" adapterType="NorthWinds.SharePoint.WebPartPages.VotingWebPartMobileAdapter, NorthWinds, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ffec2e2af2b4c675" />
注意
アダプター クラスをサーバー ファームに適合させるには、すべてのフロントエンド Web サーバー上の compat.browser ファイルを上述したように変更する必要があります。既存の compat.browser を独自の compat.browser ファイルで上書きしないでください。他の SharePoint Foundation ソリューション プロバイダーで作成したアダプター マッピングが取り消される可能性があります。アダプターを SharePoint Foundation 機能の一部として展開することを検討してください。FeatureActivated(SPFeatureReceiverProperties) イベント ハンドラーで、必要な <adapter> 要素をすべてのフロントエンド Web サーバーの compat.browser ファイルに追加するタイマー ジョブ (SPJobDefinition) を作成するためのコードを追加します。タイマー ジョブを使用した、すべてのサーバー上の compat.brower ファイルのプログラムによる編集の詳細については、「[方法] すべての Web サーバーでコードを実行する」を参照してください。
アダプターを安全なコントロールとして登録する
アダプター クラスを安全なコントロールとして登録する必要があります。
ヒント アダプターを登録する場合は、SharePoint Foundation ソリューションでアダプターを展開することをお勧めします。このセクションの手順は、開発コンピューターが単一のフロントエンド Web サーバーである場合に限り必要です。SharePoint Foundation ソリューションを使用すると、ソリューションが展開されたときに、すべてのフロントエンド Web サーバーのコントロールを安全なコントロールとして自動的に登録できます。ソリューションの展開を使用して安全なコントロールとして登録する方法の詳細については、「ソリューションの概要」、「ソリューションを手動で作成する」、および「ソリューション スキーマ」を参照してください。
Visual Studio プロジェクトで、webconfig.*.xml フォームの名前で XML ファイルを追加します。* は、所属する会社名か、他の SharePoint Foundation ソリューション プロバイダーが使用していないような名前で置き換えます。
<action> 要素を、以下のマークアップに示されるファイルに追加します。<SafeControl> 要素の TypeName 属性はアダプター クラスの名前にできます (UserTasksWebPartMobileAdapter など)。同じ名前空間に複数のアダプター クラスが存在する場合は、"*" を TypeName の値として使用できます。次に例を示します。
<action> <remove path="configuration/SharePoint/SafeControls/SafeControl[@Assembly=MyCompany.SharePoint.WebPartPages.MobileAdapters3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=yourAssemblyPublicKeyToken']" /> <add path="configuration/SharePoint/SafeControls"> <SafeControl Assembly="MyCompany.SharePoint.WebPartPages.MobileAdapters3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=yourAssemblyPublicKeyToken" Namespace="MyCompany.SharePoint.WebPartPages.MobileAdapters3" TypeName="*" Safe="True" AllowRemoteDesigner="True" /> </add> </action>
注意 "*" を TypeName の値として使用すると、名前空間のすべてのクラスが安全なコントロールになります。安全なコントロールとして指定してはならないクラスがアセンブリにある場合は、それらを別のアセンブリに移動するか、"*" を使用しないようにします。
<SafeControl> 要素および webconfig.*.xml ファイルの詳細については、「[方法] 追加の .config ファイルを作成する」と「Web.config ファイルを使用して作業する」を参照してください。
ファイルを保存します。このファイルは、開発コンピューターの %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\CONFIG フォルダーにコピーする必要があります。開発コンピューターでコピーする最も簡単な方法は、以下の行をビルド後に実行するコマンド ラインか、ビルド後に実行するコマンド ラインで実行されるバッチ ファイルに追加することです。
注意
このコードは、「[方法] ツールの場所を PATH 環境変数に追加する」の推奨事項に従っていることを前提としています。
xcopy /y webconfig.MyCompany.xml "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\CONFIG" stsadm –o copyappbincontent
stsadmn.exe コマンド copyappbincontent は、webconfig.*.xml で定義されている "<action>" を実行します。この場合、アダプターに対応する新しい <SafeControl> 要素が Web アプリケーションのルートにある web.config ファイルに挿入されます (最初に、アダプター用の既存の <SafeControl> 要素が削除されます。これより、<SafeControl> 要素を重複させることなく、すべてのビルドで stsadm の操作を再実行できます)。copyappbincontent と stsadm.exe の詳細については、「Stsadm コマンドライン ツール (Windows SharePoint Services)」と「Copyappbincontent : Stsadm 操作 (Office SharePoint Server)」を参照してください。