しばやん雑記

ASP.NET とメイドさんが大好きなフリーランスのプログラマーのブログ

WebMatrix と FuelPHP を使って Web アプリ開発をしてみた

ちょっと前になるんですが、どうしても PHP での開発をしないといけなくなったので義務として WebMatrix と、めんたろ社長におすすめして貰った FuelPHP で開発することにしました。

FuelPHP » A simple, flexible, community driven PHP5.3 framework.

FuelPHP は PHP 5.3 以上で動作する、良い感じな MVC フレームワークです。開発スタイルは ASP.NET MVC やってたら割と親しみやすい感じかと思います。

で、早速 WebMatrix を使って開発環境を作ります。当然ながら PHP なので、PHP の空のサイトを選んでおきましょう。

f:id:shiba-yan:20130924223720p:plain

サイトの作成中に PHP が無い場合はインストールしてくれます。便利ですな。

FuelPHP のインストールは手動で行うしかないので、公式サイトから現時点での最新版である fuelphp-1.6.1.zip をダウンロードして展開します。

f:id:shiba-yan:20130924224419p:plain

docs は単なるドキュメントなので、それ以外を WebMatrix で作成したフォルダに全部コピーします。そして WebMatrix 上で F5 を押すとこんな感じになるはずです。

f:id:shiba-yan:20130924224610p:plain

何となくそれっぽくなりましたね。

この段階で実行してみると 403 エラーになります。ドキュメントルートに何もないから当然ですね。

f:id:shiba-yan:20130924224912p:plain

Apache などで動かす場合には public 以下をドキュメントルートにするのが一般的ですが、WebMatrix の場合は開いているフォルダがドキュメントルートになってしまうので、このままだと上手く動きません。

なので、IIS の URL リライトモジュールを使ってパスを書き換えてあげることにします。めんどくさい人は、以下の Web.config をコピペすれば良いと思います。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="Redirect Static Resources" stopProcessing="true">
                    <match url="^(ico|assets|css|img|js)(.*)$" />
                    <action type="Rewrite" url="public/{R:1}{R:2}" appendQueryString="false" />
                </rule>
                <rule name="Rewrite Root" stopProcessing="true">
                    <match url="^(.*)$" ignoreCase="false" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="public/index.php?/{R:1}" appendQueryString="true" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

これを Web.config という名前でルートに保存して、もう一度実行するとエラーメッセージが変わります。

f:id:shiba-yan:20130924225606p:plain

何やら composer.phar update というコマンドを実行しろと言っていますね。composer.phar というのはよく分かっていないですが、 NuGet 的なものみたいです。

素直にコマンドを実行して、もう一度実行するとちゃんと FuelPHP のデフォルトページが表示されました。

f:id:shiba-yan:20130924230148p:plain

これで開発の準備は出来たので、あとは好きなようにコードを書くだけです。

中には外部からアクセス可能な場所にソースを置いていることが気になる人もいると思いますが、適切に ACL の設定を行いさえすれば問題ないですね。

これに関係して、ウェブマトリクスマンに WebMatrix 最終奥義というものを教えてもらったので、近々面白いことをしようかと思います。

WebMatrix 3 と iisnode の環境で WebSocket を有効にする方法

WebMatrix 3 を使うと簡単に Node.js と Socket.IO の開発環境を作ることが出来ますが、Socket.IO で WebSocket を使おうとするとコネクションが途中でフリーズしてしまいます。

f:id:shiba-yan:20130725010424p:plain

本来なら 101 Switching Protocols で HTTP から WebSocket への切り替えになるのですが、Pending のまま応答がありません。

調べてみると、IIS 8.0 Express ではデフォルトで WebSocketModule が有効になっているので、iisnode の WebSocket と競合してしまっていたようです。

Tomek on Software: How to use WebSockets with node.js apps hosted in iisnode

なので、大人しく iisnode の人に従って、IIS に組み込まれている WebSocketModule を無効にする設定を Web.config へ追加します。

<system.webServer>
    <!-- IIS の WebSocketModule を無効にする -->
    <webSocket enabled="false" />
</system.webServer>

これで試してみると、今度は以下のようなエラーになってしまいました。

f:id:shiba-yan:20130725010824p:plain

どうやら Web.config では webSocket 要素での設定変更が許可されていないようです。

仕方ないので applicationhost.config を開いて、configSections 要素内にある webSocket の設定を以下のように修正します。

<!-- overrideModeDefault を Allow に変更する -->
<!--<section name="webSocket" overrideModeDefault="Deny" />-->
<section name="webSocket" overrideModeDefault="Allow" />

これで Web.config から webSocket の設定を変更出来るようになります。

そしてもう一度試してみると、今度はバッチリと 101 Switching Protocols で HTTP から WebSocket への切り替えが行われました。

f:id:shiba-yan:20130725011201p:plain

そういえば、WebMatrix 2 の時は iisnode のバージョンが古くて WebSocket に対応していませんでしたが、WebMatrix 3 で入ってくる iisnode は 0.2.4 だったので、WebSocket が使えるバージョンになっていました。

この手順でも WebSocket が使えない場合は、一度 iisnode を削除してから WebMatrix の Node.js テンプレートを選んで、インストールし直すのが良いかもしれません。

WebMatrix 2 正式版がやっとリリースされました

結局ベータが出てから何か月かかってるんだという感じですが、ついに今朝正式版がリリースされたようです。

WebMatrix 2 is Released! + New Windows Azure Features - Windows Azure - Site Home - MSDN Blogs

Windows Azure チームのブログで紹介されるのも時代の流れですかね(何

ということらしいので、試してみたいですね。

f:id:shiba-yan:20120907084004p:plain

しかし、Web PI だと非常に残念なことになっているのでウェブマトリクスマンの活躍に期待したいです。

WebMatrix 既に 1 周年



折角なのでデカいバナーを張ってみました。

WebMatrix は WordPress などのインストールには最適だと思いますので、是非 MS 系技術者以外の方に使っていただきたいですね。そして流石にもうそろそろ WebMatrix 2 が出てもいいと思うんですが、今のところはベータ版で我慢してください。

ちなみに WebMatrix 2 を使った WordPress のインストール、デプロイに関しては以下の記事も参考にどうぞ。

WebMatrix 2 Beta で WordPress をデプローイ!する (1) - インストール編 - しばやん雑記

WebMatrix 2 Beta で WordPress をデプローイ!する (2) - ExpressWeb へデプロイ編 - しばやん雑記

そして忘れちゃいけない WebMatrix のスーパーヒーロー(非公式)であるウェブマトリクスマンのアカウント↓

http://twitter.com/WebMatrixMan

WebMatrix 2 Beta で WordPress をデプローイ!する (2) - ExpressWeb へデプロイ編

前回では WebMatrix 2 Beta を使ってローカルに WordPress をインストールしました。今回はローカルにインストールした WordPress を ExpressWeb へデプローイ!してみたいと思います。やっとですね。

まずは ExpressWeb を使えるようにしておかないとダメなんですが、今は無料お試しがあるので非常に楽チンですね。

ExpressWeb > お申し込み > 無料お試しサービス

無料お試しから、そのまま本契約に出来るのが非常に便利だと思います。これはデータジャパンさんグッジョブすぎますね。

それでは ExpressWeb のコントロールパネルにログインにして、Web サイトを選択すると以下のような画面になります。今回、自分のアカウントではサブドメインを追加しているので、無料お試しとは少し違うかもしれません。

いろいろ消してありますが気にせずに。次はタブにある「管理」をクリックすると、パスワードを入力するフォームと「有効」ボタンがあるので、パスワードを適当に入力して「有効」ボタンを押すと完了です。

そして再度「管理」タブを読み込みなおすと、以下のように発行設定ファイルのダウンロードリンクが表示されるので、クリックしてダウンロードしておきましょう。

これで WebMatrix からデプロイする準備は終わりましたが、MySQL のユーザー作成とデータベース作成が必要になるので、こっちも行っておきます。管理画面の「データベース」から「MySQL 5.1」を選ぶと、データベースとユーザーの追加が出来ます。

これで管理画面での作業は終わりなので WebMatrix に戻ります。WebMatrix の「Run」ボタンの隣にある「Publish」ボタンをクリックしてください。すると、Web Deploy の設定を入力するフォームが表示されます。

基本的には Tasks にある「Import publish settings」をクリックして先程ダウンロードした発行設定ファイルを指定すると、ユーザー名とパスワード以外は入力されるので、あとは手動で未入力になっている部分を入力してください。

全て入力が完了したら「Validate Connection」をクリックして設定が正しいか確認しておきましょう。サーバへの接続に成功した場合には、ボタンの隣に以下のようにメッセージが表示されます。

接続に成功したら「Save」ボタンをクリックして設定を保存しておきます。すると、以下のようなダイアログが表示されますが、互換性をチェックするかどうか聞いているだけなので、とりあえず「Yes」を選んでおけば問題ありません。

すると WebMatrix が自動でデプロイ先のサーバに必要なコンポーネントがインストールされているか確認してくれます。

ExpressWeb は WordPress に公式で対応しているので、当然ながら全て Available になります。確認したら「Continue」をクリックします。

長かったですが、ようやくデプロイの手前まで来ました。これが最後のダイアログで、これから実際にデプロイされるファイルの一覧とデータベースが確認できます。一度デプロイしておけば、次回からは変更のあったファイルだけを自動で対象としてくれるので非常に便利です。

データベースは基本的に上書きされるので、更新する場合には注意が必要です。とりあえず問題がなければ「Continue」ボタンを「デプローイ!」という掛け声とともにクリックしてください。

デプロイが開始されると通知バーが表示されます。多少時間がかかる場合にもあるので、気長に待ってください。

デプロイが無事に完了すると URL リンクが表示されるので、早速クリックして確認してみましょう。

しかし、ExpressWeb にページ作りたての環境でデプロイを行うと、サンプルページが表示されてしまいます。

ポーン(  Д )⌒Y⌒Y⌒Y⌒Y⌒Y⌒...。....。コロコロ

となるかもしれないですが、これはサンプルページである default.aspx の優先順位が WordPress の PHP よりも高いだけなので、FTP やファイルマネージャから default.aspx 削除してあげるだけで解決します。

削除が終わったら、もう一度確認してみましょう!

今度はばっちり WordPress が表示されました!これで WebMatrix を使って ExpressWeb へのデプロイはすべて完了です!

まだ書く元気があれば、WebMatrix で WordPress のファイルを編集したりしてみたいと思います。

WebMatrix 2 Beta で WordPress をデプローイ!する (1) - インストール編

仕事では PHPer やってるんですが、基本的に自社で最初から開発してるので、既存のアプリケーションって使ったことがないんですよね。

今回、ExpressWeb さんの企画に乗っかってインストールからデプロイまでやってみました。まずは Web PI で WebMatrix 2 Beta をインストールします。

WebMatrix 2

上のページにアクセスし「Try the latest Beta」ボタンをクリックすると Web PI のインストールと WebMatrix のインストール画面が表示されます。基本的には以下のページに書いてある方法と同じなので、参考にしてください。

WebMatrix のインストール手順 | MSDN

WebMatrix のインストールが終わって、起動してみると 3 つのボタンが表示されます。今回は WordPress をインストールしたいので「App Gallery」を選びます。

するとアプリ一覧が表示されるので、サイドバーから「ブログ」を選択し、右側に表示された一覧から「WordPress 日本語版パッケージ」を選択します。英語版も存在しているので注意してください。

Site Name は作成するブログの名前を付けておくのがいいと思います。日本語もちゃんと使えます。

「Next」をクリックすると MySQL がインストールされていない場合のみ、以下の画面が表示されます。

MySQL のインストールは WebMatrix が自動で行ってくれますが、MySQL の root アカウントのパスワードだけは入力する必要があります。ここで注意する点は複雑なパスワードでないとインストールに失敗してしまうということです。しかも入力時は警告メッセージなどが出ないので、最初から半角英数字記号を混ぜておくのがベストでしょう。

「Next」をクリックするとエンドユーザーライセンスが表示されます。この時に直接ファイルのみダウンロードするためのリンクも表示されるので、パッケージを解析したい場合に使えますね。

とりあえず読んで「I Accept」をクリックします。するとダウンロードとインストールが始まるので、ここはひたすら待ちましょう。

インストールが完了すると、今度は WordPress の設定を行っていきます。

Application parameters といくつか入力する項目があります。

  • パスワード用のユニークキー
  • 安全なパスワード用のユニークキー
  • 認証用のユニークキー
  • 認証用の第2ユニークキー

正直、何に使われるのか・何を指定すればいいのかさっぱりわかりませんよね。でも、安心してください。WordPress.org でオンラインジェネレータが公開されています。

https://api.wordpress.org/secret-key/1.1/

このページにアクセスすると、以下のように PHP の形式として文字列が出力されます。

define('AUTH_KEY',        'vGKrqj;uaeJeN!Na&K&punEbAO`@erFQ,#IW+_3]08|a18vUDoWF.pNFaIbo/)-~');
define('SECURE_AUTH_KEY', '^Iro{kCpKLWKse: bwRg11yMYP<;[A^NlClIg,pkQ/q.=Gmd0Lc6=~LU@L^*+9j=');
define('LOGGED_IN_KEY',   'p5iT(;/n qM`|x#@L$]$7lx:xr}N5&CT/s=g!jdC+<-HR;-tB/[Ccsxm.c^}FAB%');
define('NONCE_KEY',       'drym6708I@O$@I-1+iTgU0Sp)Lrp}HrX%=1L2T]5Y`j<nEY3/xBZD9VKB3[H]JJ<');

右側のランダムになっている文字列を、入力フォームの上から順番にコピペするだけで OK です。

そして「Next」をクリックすると WordPress のインストールが実行されて、完了すると WebMatrix のメイン画面が表示されます。

それでは WordPress のインストールの続きを行っていきますので、左上にある「Run」ボタンをクリックします。するとブラウザが起動して 以下のような WordPress のインストール画面が表示されます。

深く考えずにブログのタイトル、管理者用のパスワード、そしてメールアドレスを忘れずに入力してください。

入力が終わったら一番下にある「インストール」ボタンを押すだけです。これで WordPress のインストールが完了しました。

「ログイン」ボタンをクリックして、先程入力したパスワードを入力すると管理画面が表示されます。管理画面についての説明は行いませんが、記事の追加やプラグインの追加削除など一通りの作業を行えます。

そして左上にあるブログ名のボタンをクリックするとブログのトップページが表示されます。

これで WebMatrix 2 Beta を使った WordPress のインストールは完了です。それでは早速 ExpressWeb へデプロイを行いたいのですが、長くなってしまったので続きはまた次回とします。

WebMatrix 2 の拡張機能を作成する (4) - リボン UI

前回から少し間が空いてしまいましたが、今回は一番拡張のし甲斐があると思われるリボン UI について説明を行いたいと思います。

基本的にリボン UI は ExtensionBase に用意されている RibbonItemsCollection コレクションに項目を追加するだけですが、非常に種類が多いので種類ごとに説明をしたいと思います。

ボタン

まずは RibbonButton クラスを使ってボタンを追加してみます。

これはボタン以外にも言えることですが WebMatrix のリボン UI では、ユーザーがクリックなどで選択した時のイベントを ICommand インターフェースを使って通知するようになってます。そのため、テンプレートにもデフォルトで DelegateCommand が追加されています。

C#

// smallImage, largeImage は 16x16, 32x32 の BitmapImage
var ribbonButton = new RibbonButton(
    "Button",
    new DelegateCommand(HandleRibbonButtonInvoke),
    null,
    smallImage,
    largeImage
);

RibbonItemsCollection.Add(ribbonButton);

今回は必要ないので null を指定していますが、ICommand を使っているので当然ながら CommandParameter を指定することもできます。

実行結果


トグルボタン

RibbonToggleButton クラスを使ってトグルボタンを追加します。

トグルボタンというのは電灯のスイッチみたいに On/Off が交互に切り替わるやつです。チェックボックスに近いものと考えてください。

C#

var ribbonToggleButton = new RibbonToggleButton(
    "ToggleButton",
    new DelegateCommand(HandleRibbonButtonInvoke),
    null,
    smallImage,
    largeImage
);

RibbonItemsCollection.Add(ribbonToggleButton);

実行結果


グループ

RibbonGroup クラスを使ってグループを追加します。

今は ExtensionBase のコンストラクタに渡した時の名前でグループが作成されていますが、それ以外にも複数の新しいグループを作ることが可能です。

C#

var ribbonGroup = new RibbonGroup(
    "Group",
    new[]
    {
        new RibbonButton(
            "Button",
            new DelegateCommand(HandleRibbonButtonInvoke),
            null,
            smallImage,
            largeImage
        )
    }
);

RibbonItemsCollection.Add(ribbonGroup);

実行結果


スプリットボタン

RibbonSplitButton クラスを使ってスプリットボタンを追加します。

スプリットボタンというのはボタンの下部分をクリックすると、さらに別のメニュー項目が表示されるタイプのボタンです。Office などでも貼り付けコマンドで利用されているやつです。

C#

var ribbonSplitButton = new RibbonSplitButton(
    "SplitButton",
    new DelegateCommand(HandleRibbonButtonInvoke),
    null,
    new[]
    {
        new RibbonButton(
            "Button",
            new DelegateCommand(HandleRibbonButtonInvoke),
            null,
            smallImage,
            largeImage
        )
    },
    smallImage,
    largeImage
);

RibbonItemsCollection.Add(ribbonSplitButton);

実行結果


メニューボタン

RibbonMenuButton クラスを使ってメニューボタンを追加します。

メニューボタンは見た目はスプリットボタンとあまり変わらないですが、ボタンとしての機能は持っていないので引数にデリゲートは指定できなくなっています。

C#

var ribbonMenuButton = new RibbonMenuButton(
    "MenuButton",
    new[]
    {
        new RibbonButton(
            "Button",
            new DelegateCommand(HandleRibbonButtonInvoke),
            null,
            smallImage,
            largeImage
        ),
    },
    smallImage,
    largeImage
);

RibbonItemsCollection.Add(ribbonMenuButton);

実行結果


スプリットボタンギャラリー

RibbonSplitButtonGallery クラスと RibbonGalleryCategory クラスを使ってスプリットボタンギャラリーを追加します。

NuGet や Extension などのようなドロップダウンするインターフェースを簡単に実装することが出来ますが、見た目の調整にはデータテンプレートを使う必要があります。

C#

var ribbonGalleryCategory = new RibbonGalleryCategory("Header");

ribbonGalleryCategory.Items.Add("Item 1");
ribbonGalleryCategory.Items.Add("Item 2");
ribbonGalleryCategory.Items.Add("Item 3");

var ribbonSplitButtonGallery = new RibbonSplitButtonGallery(
    "Gallery",
    new DelegateCommand(HandleRibbonButtonInvoke),
    null,
    new DelegateCommand(HandleRibbonButtonInvoke),
    new[]
    {
        ribbonGalleryCategory
    },
    smallImage,
    largeImage
);

RibbonItemsCollection.Add(ribbonSplitButtonGallery);

実行結果

ちなみにデータテンプレートを使うと以下のようなインターフェースを作ることもできます。


コンテキストタブ

RibbonContextualTab クラスを使ってコンテキストタブを追加します。

リボン UI の特徴の一つとして、現在の操作内容によってタブが表示される機能がありますが、このクラスを使うと簡単に実装できます。しかし、操作している内容での切り替えは手動での出し分けが必要です。

C#

var ribbonContextualTab = new RibbonContextualTab(
    "NewTab",
    new[]
    {
        new RibbonGroup(
            "Group",
            new[]
            {
                new RibbonButton(
                    "Button",
                    new DelegateCommand(HandleRibbonButtonInvoke),
                    null,
                    smallImage,
                    largeImage
                )
            }
        )
    }
);

RibbonItemsCollection.Add(ribbonContextualTab);

実行結果

WebMatrix で一番拡張しがいのあるリボン UI の説明はこれで終了です。次回はダッシュボードの拡張について説明したいと思います。お疲れ様でした。

WebMatrix 2 の拡張機能を作成する (3) - 通知・ダイアログ

前回で基本的な拡張機能の仕組みについては理解してもらえたと思いますので、今回からは拡張機能を使用してできることを画像とサンプルコード多めで紹介したいと思います。

まずは機能的にシンプルで利用頻度も高そうな、通知とダイアログから説明します。

通知を表示する

ウェブサイトを作成した時になどに画面の下の方に出てくる黄色いバーを表示したい場合には ShowNotification メソッドを使います。通知なのでボタンを追加したりはできませんし、一定時間で非表示になります。

C#

WebMatrixHost.ShowNotification("テストメッセージ");

実行結果

引数で指定したメッセージが表示されていることが確認できます。

基本的にはテキストのメッセージしか表示できませんが、オーバーロードされたメソッドを使うことで、一つだけハイパーリンクを表示することが出来ます。

C#

WebMatrixHost.ShowNotification("テストメッセージ", "アクション", () =>
{
    // アクションが選択された時の処理
});

実行結果

この場合では「アクション」をクリックすると 3 つめの引数で指定したデリゲートが実行されます。

ダイアログを表示する

WPF や WinForm のようなダイアログを表示したい場合には WebMatrixHost.ShowDialog メソッドを使います。

ShowDialog メソッドは以下のような 4 つのオーバーロードされたメソッドを持っていますが、基本的には title と content を指定するだけでダイアログの表示は可能です。

bool? ShowDialog(string title, object content);
bool? ShowDialog(string title, object content, DialogSize dialogSize);
bool? ShowDialog(string title, object content, MessageBoxButton buttons, MessageBoxResult defaultButton);
bool? ShowDialog(string title, object content, DialogSize dialogSize, MessageBoxButton buttons, MessageBoxResult defaultButton);

DialogSize は列挙子となっていて、以下のような値を取ります。意味は名前から理解できると思いますので省略します。

  • SizeToContent
  • Small
  • Medium
  • Large

MessageBoxButton と MessageBoxResult はダイアログに表示するボタンの種類と、デフォルトで選択されるボタンの設定なので特に説明は必要ないですね。

例えば、以下のコードではシンプルな文字列だけを表示するダイアログが表示されます。

C#

WebMatrixHost.ShowDialog("WebMatrix サンプル", "これはテストメッセージですよ");

実行結果


ユーザーコントロールを表示する

WebMatrix ではダイアログとして UserControl を表示出来るようになってます。content に UserControl のインスタンスを指定すれば自動的にコンテンツとして表示されます。

以下のコードでは CustomDialog を表示するダイアログが表示されます。

C#

WebMatrixHost.ShowDialog("WebMatrix サンプル", new CustomDialog());

実行結果

デフォルトの「OK」「Cancel」ボタンを非表示にしたい場合には IDialogContent インターフェースを実装します。その代わりに UserControl がダイアログを閉じる機能を実装している必要があります。

IDialogContent インターフェースは CloseDialog イベントだけを持っていて、このイベントを呼び出すことで表示中のダイアログ、つまり自分自身を閉じることが出来ます。サンプルとして C# と XAML のコードを載せておきます。

C#

public partial class CustomDialog : UserControl, IDialogContent
{
    public event EventHandler<EventArgs> CloseDialog;

    private void CloseButton_Click(object sender, RoutedEventArgs e)
    {
        if (CloseDialog != null)
        {
            CloseDialog(sender, e);
        }
    }
}

XAML

<UserControl x:Class="WebMatrixExtension1.CustomDialog"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             Width="300" Height="300"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Rectangle Fill="Red" Margin="0,0,0,50" />
        <Button IsDefault="True" Width="90" Height="30" Content="Close" VerticalAlignment="Bottom" Click="CloseButton_Click" />
    </Grid>
</UserControl>

実行結果

デフォルトのボタンが表示されず、XAML で指定したボタンのみが表示されていることが分かります。UserControl を載せることが出来るので、わざわざウィンドウを用意する必要がありません。

WebMatrix 自体が機能を提供しているので、テーマに合った違和感のない表示が出来るのが素晴らしいですね。次回はリボン UI のカスタマイズについて説明したいと思います。お疲れ様でした。

WebMatrix 2 の拡張機能を作成する (2) - IExtension と MEF

さて、前回でプロジェクトまで作成できたので、とりあえずプロジェクトの中身を確認しておきます。

上から順番に見ていきましょう。

まずは DelegateCommand ですが、これは MVVM やったことのある人ならみんな知ってると思います。WebMatrix は WPF で作られている関係もあり、ボタンやメニューが選択されたことを通知するために ICommand インターフェースが使われています。DelegateCommand は I。Command を実装していて、コンストラクタで渡したラムダ式やデリゲートを実行する機能を持っています。

そして Star_16x16.png と Star_32x32.png はアイコン画像です。主にボタンとコンテキストメニューで使います。

最後は WebMatrixExtension になりますが、これが拡張機能の心臓部ともいえる IExtension インターフェースを実装しているクラスです。実際には IExtension をそのまま実装しているわけではなく、予め用意されている ExtensionBase クラスを継承しています。

それでは生成されているコードを見ていきます。

/// <summary>
/// A sample WebMatrix extension.
/// </summary>
[Export(typeof(IExtension))]
public class WebMatrixExtension2 : ExtensionBase
{
    // 省略
}

まずはクラス宣言です。MEF を使っているので Export 属性を使って IExtension 型として外部に公開するようにしています。ExtensionBase を継承していることもわかりますね。

/// <summary>
/// Initializes a new instance of the WebMatrixExtension2 class.
/// </summary>
public WebMatrixExtension2()
    : base("WebMatrixExtension2", "1.0")
{
    // Add a simple button to the Ribbon
    RibbonItemsCollection.Add(
        new RibbonGroup(
            "My Group",
            new IRibbonItem[]
            {
                new RibbonButton(
                    "My Button",
                    new DelegateCommand(HandleRibbonButtonInvoke),
                    null,
                    _starImageSmall,
                    _starImageLarge)
            }));
}

次はコンストラクタです。ExtensionBase クラスが引数付きのコンストラクタを持っているので、コンストラクタでパラメータ付きで呼び出してあげましょう。パラメータとして拡張機能の名前とバージョンを指定します。

ここで指定した名前はこの後に紹介予定のダイアログやリボン UI でのタイトルなどのデフォルト値として使われます。

そして肝心の処理としては、ここではリボン UI にグループとボタンを追加しています。リボン UI の操作方法は別で説明しますので、今回はボタンを追加しているということだけ理解していただければ問題ありません。そしてボタンが押された時には DelegateCommand を使って HandleRibbonButtonInvoke メソッドへ処理を委譲しています。

/// <summary>
/// Called when the Ribbon button is invoked.
/// </summary>
/// <param name="parameter">Unused.</param>
private void HandleRibbonButtonInvoke(object parameter)
{
    if (WebMatrixHost.ShowDialog(this.Name, "Open a browser window for the site?").GetValueOrDefault())
    {
        Process.Start(WebMatrixHost.WebSite.Uri.AbsoluteUri);
    }
}

最後にボタンが押された時の処理を実装している HandleRibbonButtonInvoke メソッドです。処理としてはダイアログを表示して「OK」が選択された場合に開いているウェブサイトをブラウザで表示するといったことをしています。

ここで注目してもらいたいのが WebMatrixHost というプロパティです。これは WebMatrix の本体機能にアクセスするために用意されていて、ダイアログの表示やウェブサイト・ワークスペースなど各種情報の取得が行えます。

ちなみに WebMatrixHost プロパティは ExtensionBase クラスで用意されているものなので、使用しない場合には IWebMatrixHost インターフェースをインポートして取得する必要があります。

[Import(typeof(IWebMatrixHost))]
private IWebMatrixHost WebMatrixHost { get; set; }

他にも Import 属性を使ってインスタンスを取得できるインターフェースは多く存在しますが、基本的に ExtensionBase クラスに用意されているプロパティで十分です。

今回見たコードはテンプレートですが、基本的にはリボン UI やコンテキストメニューにボタンを追加して処理を実行するのが WebMatrix の拡張機能の考え方です。他にもプロパティやイベントなどがありますが、それは次回以降に紹介していきたいと思います。お疲れ様でした。