multiselect」という題で複数選択を行えるjQueryのプラグインを解説したけれど、先日これを使う機会がまたあり、触ってみたらEncoding周りで苦労したので解説しておく。前回解説したときは英語を使用していたので気付かなかったのだが、日本語で使用するとプラグインそのままだと不便な箇所がいくつかあったのでそれの修正点もあわせて解説していく。PythonをサーバとしフレームワークにはDjango-nonrelを使用している。こちらのgithubからソースコードをダウンロードしよう。cloneでダウンロードするとajax対応ではないソースコードが落ちてくるので画面右上のDownloadボタンから取得するように。ZIPファイルを解凍すると色々とファイルが入っているけれど、今回は下図のようなフォルダ構造にした。実際のHtmlとプラグインを使用するJavascriptコードは下記のようになる。}}という記述はDjangoのテンプレート機能なので他のフレームワークを使用している場合は適切な形に修正して欲しい。前回解説したときと比べて変わったのはlocalizationプラグインを使用してローカライズを行っている箇所だ。下記にui.multiselect-ja.jsの内容を示す。errorDataFormat:"データ形式が予期しない形です。#{value}\n\n処理は中止されました。errorRequest:"データ取得中にエラーが発生しました。#{status})"});これで上記の内容で日本語表示される。ついでui.multiselect.jsのほうに手を加える。},デフォルトではサーバに投げるクエリ文字列をescape()でエンコーディングしているけれど、escapeが出力するエンコーディングはW3C標準ではないので、Django側で受けたときに正しくデコードできない。そのためescapeに変わってencodeURIComponent()を使用する。それに併せて使い勝手の上でmultiselectのそのままの仕様だと日本語入力しづらいことこの上ないので、下記のように入力にあわせた自動検索を無効化しておく。Math.max(that.options.searchDelay,1));}上記に併せてsearchDelayオプションも不要になったので気になる人は削除しておこう。これでクライアント側の準備は整ったのでサーバ側を見てみよう。リクエストハンドラーとして下記の一文をurlpatternsに追加しておく。実際のリクエストハンドラーは下記。HttpResponse(results)検索文字列を取得するところでごにゃごにゃとやっている解説は下記の通り。query.encode('ascii')でobjectから文字列に変換している。urllib2.unquote()でエスケープ文字を普通の文字に変換している。最後にUTF8でデコードして完了。これで日本語でも複数選択のプラグインが正常に動作するはずだ。いじり始めたので今後のための備忘録とか、いまさらの内容とか。読んでみて、実際にちょこちょこいじり始めたら、しょっぱなの開発サーバをコマンドラインから起動するところではまったので今回はそれを。ランチャーを使えばこんなところ問題ないんだろうけど、やっぱりこういうのを見せられるとコマンドをぺこぺこ打つのをまねしたくなっちゃうわけで。フォルダで下記のコマンドを入力してね、となっているけれど動かない。下記の値が追加されているのだけれど、それが認識されない。追加されているのはユーザー環境変数のほう。へ先ほどのパスを追加する(;で他のパスと区切るのを忘れないように)。開発サーバ用スクリプトが認識されているはずだ。親フォルダへ移動する。フォルダが下記パスだとする。c:\gae\helloworld上記の場合は下記フォルダへ移動する。c:\gaeこの状態で下記コマンドを実行すると開発サーバが正常に起動される。helloworld/と、まぁ大した内容ではないのだけれど、ドキュメントのままだと動かんね、ということで。Clipでもキャプチャを実装していたのだが、今回チヌかかり釣りMEGAでも同様のことをやりたかったので、昔のソースコードを引っ張り出してきて再確認したので、それをまとめておく。使用しているのは下記ブログポストで紹介されているライブラリ。Clip実装時の上記ブログポストのソースコードで実装方法を紹介する。ともに文字列を返却するようになっているため。キャプチャでの検証結果が代入されている。表示するばキャプチャが表示されているはずだ。MVCで稼動しているサイトへアップロードする方法を解説する(元ネタはStackOverflow)。}}データをポストするときのフォーマットを正確に作ってやって、そこに送りたいデータをはめ込むだけ。MVCサイトを動作させた状態でクライアントを実行すればサーバ側でファイルを受け取り保存することが可能なはずだ。ImapX編に引き続き、今回は下記ライブラリを使用してGmailの内容を取得する方法を解説する。Modelなのでとっつきにくいけれど、慣れればImapX以上の柔軟さがあるし、何よりOSSなので自分で問題解決できるのが良い。引数は指定のsequenceがUIDかどうかの判定用。x.Message));}一見して分かる通りかなり癖があるのでとっつきにくい部分もあるが、慣れてしまえば細かいところまで制御できるので非常に有用だ。ひとつサンプルとして未読メッセージのみ取得する方法を紹介しておく。送信されてきたメールをIMAPで取得、解析して内容をDBに突っ込もう、というツールが必要だったので良いライブラリが無いかと探して見つけたのが下記。Modelがよく設計されているので至極簡単に使えて便利。Sourceではないので何か問題があったときに何も対処できないし、作者のレスポンスもかなり遅いので対応は期待できないので注意が必要だ。Gmailを使う画像の添付があるIMAPを使う(未読メールのみ取得したいため)GmailのアカウントでIMAPを使えるようにする方法は下記を参照のこと。IMAPで、実際のソースコードはこんな感じ。commands.txtを参照して欲しい。POP3で良いのならOpenPop.NETもかなり使いやすい。サンプルコード集も分かりやすい。Firstの実装方法を解説した。今回はMySQLを使用する方法を解説する。前回のソースコードをそのまま流用するのでこちらからダウンロードして欲しい。・セットアップ下記からそれぞれ自分の環境のものをダウンロードして欲しい。Windows」を参考に下記のようにセットアップした。Networking"をチェックする。ポート番号3306のままにする。Service"をチェックする。automatically"をチェックするルートパスワードを入力する。machines"はチェックしないほうが良いよ"execute"をクリックしてインストール終了まで待機する・接続文字列ついでWeb.configの接続文字列を下記のように変更する。/>providerNameがMySqlClientになっているのに注目して欲しい。前述のConnector/Netがインストールされているとmachine.config(C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config)のDbProviderFactoriesセクションにMySql.Data.MySqlClientが登録されているので特に他の記述は必要ない。FirstWindowsサービスでMySQLが動作しているのを確認し実行してみよう。FirstがDatabaseを作成してくれて正常動作するはずだ。案に相違して「データベースSengokuが見つからない云々」という例外が発生する。FirstがCTP5のためサポートされていないのかどちらなのかよく分からない。Databaseを作成した。※ログイン時にUsernameとPasswordが尋ねられる。セットアップ時にPasswordの設定はするけれどUsernameの設定は無かったので面食らうと思うがここではrootと入力すれば良い。Database上に作成した。Databaseを確認するとTableが2つできているのが確認できると思う。・実行この状態で実行すると下図のように正常動作する。武将登録やコメント追加も行える。Serverと同じ挙動だった。Firstが正式リリースされたときにここらへんの修正が入るのか、それともConnector/Netのほうの修正が必要なのかは不明だが、現状さしたる不都合は無さそうだ。First:CTP5と一緒に評価してみた。2008を使用するがそのうちMySQLを使って解説したい。・セットアップそれぞれ下記からインストールして欲しい。FirstはNuGetを使用したほうがより簡単に導入できるのでそちらの方法をお勧めする。NuGetを使用しての詳細な説明はこちら。EFCodeFirst”と入力するだけだ。MVCを触る人は下記を参考にしてもらいたい。MVC3の基礎を知ることができるので有用だ。これと合わせてユニットテスト用にRepositoryパターンなども勉強すると良いだろう。・今回のアプリ今回は次のようなWebアプリを作成する。武将の一覧があり、武将の登録、編集、削除が行え、かつ武将から武将へのコメントも行える。コメントの削除、編集も行える。Firstでデータストレージを作成するので前もってDatabaseやTableを用意しておく必要がない。Modelは下記になる。}Bushouクラス、Commentクラスともにvirtual属性以外のものがいずれTableの各列となる。FirstはConvention(規約、協定みたいなもの)があり、たとえばBushouクラスであればID、またはBushouIDとなっているものを主キーとみなし自動的に設定を行ってくれる。外部キーも同様に、今回の例ではないがCommentクラスにBushouIDなどがあればそれを外部キーとして設定を行ってくれる。ここでは、コメントされる人、コメントする人、と2つの外部キーがあるためConventionの法則に則っていないのでその設定は自動で行われない。いう場合はDbContextのOnModelCreatingを使い自前で設定を行う。APIと呼ばれるもので、大抵の設定はこれで行えてしまう。APIの詳細な資料はこちらを参照してほしい。APIを使用せずとも明示的にフレームワークに通知することができる。Annotationもサポートされている。[Required]属性や[MaxLength]属性などでデータの説明を行えるようになっている。MVC3と完璧に協調するのでクライアントサイド検証や、サーバサイド検証をフレームワークが自動で行ってくれる。ここに一つ問題がある。Annotationのデフォルト言語は英語のためエラーメッセージはすべて英語になってしまう。Modelを検証と日本語に対応したものに更新しよう。}BushouクラスのNameプロパティやAddressプロパティにそれぞれRequired属性とStringLength属性が付与されている。ErrorMessageResourceTypeでリソースクラスの指定、ErrorMessageResourceNameでリソースキーの指定を行っている。リソースクラスを使う方法以外にもErrorMessageを直接指定する方法があるが、ここでは前者を採用している。ちなみにこのリソースクラスを使用する方法は多言語対応と同じ方法だ。リソースクラスの追加方法を説明する。下図のようにASP.NETフォルダの追加からApp_GlobalResourcesフォルダを追加し、ErrorMessages.ja.resxとErrorMessages.resxを追加しよう。ErrorMessages.ja.resxに下図の内容を追加する。ModifierをPublicにすることを忘れないように注意しよう。ErrorMessages.resxにも同様のキーを追加しておこう。ここにキーを追加しておかないと実行時にリソースキーが見つからないというエラーになる。Annotationのデフォルト言語を英語以外にする方法は現状無い日本語のみを対象とするアプリケーションでは今回のような多言語対応の方法だとかなり冗長になる。Annotationのデフォルトエラーメッセージ自体を変更できないかと色々と調べたけれどその方法はなさそうだ。いうのもReflectorでSystem.ComponentModel.DataAnnotations.dllの中身を調べたけれど、エラーメッセージ表示部分で内部リソースを直接参照しており、そのリソースをアセンブリ外部から操作できないようになっていた。MVC3のアプリケーションの説明をする。Applicationを選択し、Emptyプロジェクトを選択しよう。名前は適当につけてほしい。ControllersフォルダにHomeControllerを追加しよう。HomeかというとデフォルトRouteを変更するのが面倒だからだ。デフォルトRouteを変更したい場合はGlobal.asax.csでRouteのマッピングを行っているのでそこで変更すればよい。最初にIndexを追加する。}ここでは面倒なのでSengokuはHomeControllerのフィールド変数としているけれど、実際のプロジェクトではユニットテストでMockオブジェクトを使用するためにデータアクセス層を分けるのでこのような実装をすることはない。詳しくはRepositoryパターンを調べ欲しい。FirstのConventionの一つでクラス名と同一のコンフィグキーを探し、その接続文字列でDatabaseに接続するというのがある。そのため下記の接続文字列をWeb.configに追加しておこう。Firstは定義されている内容でDatabaseを作成してくれる。2008を使っているがExpressでも同様の動作をする。Index.cshtmlを追加する。ViewからIndex.cshtmlを追加しよう。templateを指定できる。ちなみにここではIListを指定しているのでtemplateの選択はできない。追加されたIndex.cshtmlを編集したもの。EngineにRazorを使用している。Razorの文法についてはこちらを参照してほしい。}</div>@modelでこのページのModelの型を指定している。Layoutで使用するASP.NETで言うところのマスターページを指定している。内部的には何も難しいことはしておらず、Modelをforeachでぐるぐると回してタグを作成している。ここで一点注目して欲しいのはコメントタグ作成部分だ。comment.CommentBushou.Nameが取得されているのが分かる。次にCreateを追加する。}とくに難しいことも無いので説明は省略する。Viewの追加からBushouクラスをModelとしたCreate.cshtmlを追加する。"Index")</div>クライアントサイドの検証を有効にするためにはWeb.configのClientValidationEnabledとUnobtrusiveJavaScriptEnabledをTrueに設定しておく必要がある。MVC3ではデフォルトでTrueになっている。_Layout.cshtmlで下記スクリプトが指定されていることを確認しよう。type="text/javascript"></script>これでStringLengthで指定されている文字数以上を入力したり、Required指定されている項目を未入力にしたりするとエラーメッセージが表示される。・まとめここまで見てきて分かると思うがかなり開発しやすくなっている。Engineとして提供されたおかげでプログラムコードとHtmlの分離が簡単になった。Annotation機能がさらに進化したおかげで検証の組み込みも簡易に行えるし、一つの設定でViewからDatabaseまで有機的に協調できているのが素晴らしい。Modelが使えるというのが良い。実際に触ってもらうと分かると思うがより開発速度が高まったのを実感できると思う。他にも今回のアプリではEditやAddCommentといった機能があるが大体ここまでで説明してきたことと一緒なので省略する。興味がある人はソースコードを添付しておくので下記から取得してほしい。ソースコード次回はデータストレージをMySQLにした場合の解説をする予定だ。First2011年1月6日木曜日Canvasにリストの中身をBindingする方法ObservableCollectionでもなんでもいいのだが、リストで保持している内容をCanvasに表示したいことはままある。Canvas.Childrenに対して単純にBindingしても予期した動作にはならない。そんな場合はItemsControlのItemsPanelTemplateを使用する。こんな風にデータをCanvas上に表示したい。TopでCanvas上の位置を保持している。上記のリストをCanvas上に配置するためのXamlを見てみよう。</ItemsControl>ポイントはItemsControl.ItemsPanelのItemsPanelTemplateを使用している箇所。Topを指定して任意の位置にデータを表示させることが可能となる。サンプルコードはこちら。(Chromeだと下記iframeが表示されない模様。Serverの状態をチェックしたくなることはままあることで、パフォーマンスを計る上でも各オブジェクトのクエリプランやら実行回数を知っておくのは悪くない。いうわけで下記クエリを実行すると下図の結果が得られる。'YourObjectName'上記のクエリからこういう結果がでる。上図でQueryPlanのリンクをクリックすると下図のクエリプランが表示される。MVCのプロジェクトをMVC2に変換をし、とあるページを追加したところ、そのページはある型(便宜上TestModelとする)を使用していたのだが、どうにもこうにもその型を認識してくれない。何をやってもObjectとしてしか認識されず非常にイライラしたのでここに解決方法を紹介しておく。解決方法と言ってもViewsフォルダー配下のWeb.configを開き、下記部分を修正するだけだ。</controls></pages>こちらに変更する。</controls></pages>これで正しく型が認識されるはずだ。ToolkitのRelayCommandの実装方法を色々と紹介する。今回はWPFで実装している。something...});2、コマンドパラメータありItemsControlのDataTemplate内要素のイベントをフックしている。ここでのDataTemplateのDataContextはDataItemになるので、単純にClickCommandをBindingしても期待した動作にはならない。そのためRelativeSrouceで一番上の親要素(Window)までたどってViewModelを取得している。CommandParameterにDataTemplateのDataContextをBindingしている。something...});3、ICommand以外をBindingWindowのLoadedイベントなどをBindingしたい場合はEventToCommandを使用する。パラメータありWindowのClosingイベントなどでパラメータを渡したい場合はPassEventArgsToCommandをTrueに設定する。something...});今回解説したようにEventToCommandを使用するとICommandに対応していないイベントもBinding可能となる。Window要素のイベントに限らずどのような要素にも適用できるのでEventToCommandを使用すればコードビハインドを経由してイベントをリレーする必要がなくなる。Japanウェブアプリ、デスクトップアプリ、モバイルアプリ、ゲームなどを開発しています。