ページ

ラベル WP7 の投稿を表示しています。 すべての投稿を表示
ラベル WP7 の投稿を表示しています。 すべての投稿を表示

2014年11月12日水曜日

[WP7] Windows Phone 7.x は 2014/12/31 でアンロックできなくなる

microsoft の Windows Store チームからメールが届いてましたが、2014/12/31 以降は Windows Phone 7.x デバイスを開発テスト用にアンロックできなくなるようですね。unlock your Windows Phone 7.x devices にある手順で 2014/12/31 までにアンロックしておけば 24ヶ月間はアンロック状態を維持できるようです。もちろん、すでにストアーにある 7.x アプリには特に影響は無いとのこと。

そうなのかぁ。すでに使ってない Windows Phone 7.5 が 1つあるけど一応アンロックしておこうかな。

2012年6月7日木曜日

[WP7] Lumia 800 を 105,000フィートまで飛ばしてみた

University of Southampton sends a Nokia Lumia 800 to 105,000 feet」 より。
こちらは Microsoft UK Education チームのブログですが、Southampton 大学が ASTRA(Atmospheric Science Through Robotic Aircraft : ロボット機による大気研究、という感じかな)の一環として Windows Phone 7.5 搭載の Nokia Lumia 800 を 105,000フィートまで飛ばしてみたということが紹介されています。
記事やリンク先には上空から撮影した美しい写真がいくつか紹介されています。(もちろん、Lumia 800 で撮影したものなんでしょうね)

大気調査用の風船に Lumia 800 を付けて飛ばし、高度 105,000フィート(32km)まで上がり、そこは –61C の世界だそうです。
データは Windows Azure で処理しているそうですが、どうやら高度 8km までは 3G で接続できていたということみたいです。図に高度 23km でパワーダウンとありますね。解説は見つかりませんが、低温すぎて機能不全をおこしちゃったのかな?けど、GPS やジャイロ搭載で通信機能まである安価な機器ってことで、観測用風船の軌道調査などに役立ちそうだってことみたいです。
確かに考えてみりゃ、GPS やジャイロ、カメラ、3G、WiFi といった機器を装備していて、かつ、無料の開発環境(Visual Studio)でアプリを作れるデバイスが数万円程度で手に入るんですからねぇ。

2012年4月23日月曜日

[Silverlight][WP7][WinRT] XAML Spy

(まだダウンロードすらしてないけど)
http://xamlspy.com/
実行中アプリの XAML の内容を閲覧することが出来るツールです。Silverlgith、Silverlight For Windows Phone、WinRT に対応してます。
現在は Preview リリースなので無料で使用できるようです。

ちなみに作っているのは Silverlight Spy と同じところみたいです。

(@biac さんのつぶやきで気付いたので以下追記)
Silverlight は Web ブラウザーを内蔵していて、それ経由でアクセスすることにより任意のアプリの XAML を見ることができるようです。参考: Connecting a Silverlight application (Silverlight Spy も同様の動きでした)

Silverlight for Windows Phone はエミュレーター上で XAP を動かすことによって XAML を見るようです。なので、XAP が入手できるアプリであれば任意のアプリの XAML を見ることができるんじゃないかと思います。参考: Connecting a Windows Phone application

WinRT は Silverlight の Web ブラウザーや Silverlight for Windows Phone のエミュレーターにあたるものが無いようで、あらかじめコードに XAML Spy と通信するためのコードを埋め込んでおく必要があるようです。参考: Connecting a WinRT application ということは、あらかじめこのコードを埋め込んであるアプリの XAML しか見ることはできないことになりますね。

うーん、そうかぁ。
WinRT ランタイムをホストするための仕様なんかが公開されれば、それ経由で XAML にアクセスすることができるかもしれませんが、そうなるまではどうしようもないんでしょうね。

2012年1月27日金曜日

[WP7] WebClient を gzip 圧縮対応させてパフォーマンスアップ

Please ship your next Windows Phone app with GZip: speed requests 50-80%」 より

どうやら Windows Phone 7.5 の WebClient は HTTP 圧縮に対応していないみたいです。
けど、WebClient をちょこちょことやってやればそんなに難しくなく圧縮に対応できるよ。そうすれば、通信の時間が短縮できてパフォーマンスアップできるかも、と。
(だから標準で対応してくれって言ってるんですね。確かにこれくらい対応しててもよさそうなもんだけど)

元ネタとなっている記事はこちら。「GZIP Compressed Web Requests in WP7 - Take 2
WebClient を使って圧縮に対応する方法が紹介されています。(ソースをダウンロードすることもできますし、NuGet から取得することもできます)

簡単に解説。(私もあまり詳しくないけど)
今どきの Web サーバーはレスポンスを gzip で圧縮して返すことができます。圧縮してデータのサイズを小さくできればネットワークの負荷を下げて効率を良くすることができるわけです。けど、毎回圧縮処理をするとそのぶん CPU 負荷があがっちゃうので良い面ばかりでもないです。
JSON や XML などといったテキストベースのデータの場合はかなり圧縮率が高くなることが期待できますが、反対に JPEG や MPEG といったもともと圧縮されているものはそれ以上圧縮しても何の意味もない、というか、かえってサイスが大きくなっちゃったり、CPU 負荷を上げたりと悪い面の方が大きくなってしまいます。
なので、圧縮を使ってるかはサーバーによっていろいろみたいです。圧縮をまったく使ってないサーバーだとか、静的な HTML ファイル等だけ圧縮してそれ以外のファイルや動的な CGI や PHP、ASP.NET などで作られるデータは非圧縮としているサーバーだとか。
で、もちろん、クライアントの側も対応していないと話になりません。
圧縮に対応しているクライアントは HTTP リクエストヘッダーに “Accept-Encoding: gzip” と入れておきます。
これが入っている時のみ、サーバーはレスポンスを gzip 圧縮して返します。(もちろん、非圧縮で返してもいい)
レスポンスが圧縮されているときはレスポンスのヘッダーに “Content-Encoding: gzip” と入っています。
上記で紹介されているコードを見ても、これと同じ事をやっています。で、レスポンスが gzip だったらレスポンスのストリームを SharpGIS.ZLib.GZipStream というもの経由で返すようにしています。

2012年1月6日金曜日

[IE][JavaScript][WP7] JavaScript と Script# と PhoneGap

進化する ECMAScript
これは、Internet Explorer チームのブログ(英文記事を日本語訳してくれたもの)ですが、Microsoft が JavaScript に対して結構本気だっていうことがよく分かる感じです。Math、String、Number やグローバリゼーションの強化案ってことでプロトタイプを作ってすでに公開しているとのこと。
そういや、以前に jQuery でもグローバリゼーション・プラグインを公開していましたね。(@IT: 「Microsoft発のjQueryグローバリゼーション・プラグイン」)

と、まあ、こういった JavaScrpt の強化についても気になるところではありますが、個人的にこの記事で一番気になったのは 「数十万行の JavaScript コードから成る Office Web アプリケーション は、主に Script# をベースに記述されており」という部分。
そういや、Script# が使われていると聞いたことがあるような気がしないでもない。
Script# っていうのは、C# で JavaScript のコードを書けるようにするっていうシロモノです。(C# をコンパイルすると JavaScript が生成される。記事にも出てくる Google Web Toolkit は Java をコンパイルすると JavaScript が生成されるヤツですね)
私もプログに取り上げたことあったなぁと検索してみたら

といったあたり。2006年のころですか。WPF/E なんて単語も出てきてて、なつかしい。(ちなみに、WPF/E は Silverlight のコードネーム)

で、先日の PhoneGap と Script# を組み合わせて使うなんてことができるとおもしろいかも、なんて思いました。
これができるなら、Windows Phone、Android、iOS すべてで動くアプリを C# で書けるってことになりそうですね。
理屈の上では PhoneGap の API をマネージドであるかのように見せかけるアセンブリ ( ここ の “Referenced Assemblies” にあたるアセンブリ) があればいいのかな?

Mono for AndroidMonoTouch を使えばプログラミング言語としては C# を使えるけど、これらは API 自体はプラットフォームごとに異なるから UI 部分なんかはそれぞれごとに作らなくちゃいけないですよね?それに対して、PhoneGap は HTML+α がベースだから UI 部分も含めて大部分が使い回し可能ってことになりそう。
時間があったら Script# について久しぶりに調べてみたいな。

# ところで、Office Web アプリケーションを作るのに使った Script# って公開されてるのと同じものなんだろうか?ひょっとして、Microsoft 社内用のバージョンがあったりするのかな?

2012年1月5日木曜日

[WP7] Coding4Fun Windows Phone Toolkit

http://coding4fun.codeplex.com/
ほぅ、こんなのあったんだ。
Windows Phone 7 用のコントロール集です。
上記にスクリーンショットがありますが、RoundButton(丸いボタン)、TimeSpanPicker(時間間隔の選択)、Pipup を使ったメッセージボックスや入力ダイアログ、アバウトダイアログなど、色選択コントロールなんかが入っています。「Addition to the Coding4Fun Toolkit - MetroFlow」 にある MetroFlow コントロールも入っています。(言葉で説明しにくいですが横配置で選択されている項目だけが広くなるようなコントロールです)
あと、bool を Visibility に変換するコンバーターなども入ってます。
Themed Image Converter は現在のテーマが “Dark” か “Light” かによって使う画像を切替えてくれるコンバーターなのかな?そりゃいいな。(しかし、ApplicationBar は UIElement じゃないからデータバインドできないよ、とかって悲しい事になりそうな気がするけど)

パッケージ(NuGet)で入れれるみたいですが、Source Code のところの Latest Version をダウンロードすれば、サンプルも含めてソースコードをダウンロードできます。(確認してないけど、NuGet の方だとサンプルは入ってないんじゃないかな)
Latest Version のソースコードをダウンロードして、Visual Studio 2010 でソリューションを開き、Coding4Fun.Phone.TestApplication を 「スタートアッププロジェクトに設定」 して実行すればサンプルをエミュレーターで動かすことができました。("Dependencies\Microsoft.Phone.Controls.Toolkit.dll" を 「ブロックの解除」 してやらないとビルドできないかもしれません)

2011年12月22日木曜日

[WP7] Windows Phone 上でアプリ開発ができるツール - TouchDevelop

TouchDevelop v2.5: new tutorial, artwork, forum, and more より。

へえぇぇぇ、こんなのがあったんですね。
TouchDevelop という Windows Phone 7 アプリです。すでにバージョン 2.5 なので結構前からあったのかな?
サイトなどを見るとわかるように開発しているのは Microsoft Research です。Microsoft Research というのは Microsoft 社の研究開発部門なので、このアプリも研究の一環なんでしょう。

で、この TouchDevelop ですが、このアプリ自体がアプリの開発環境であり、実行環境にもなっています。
アプリの開発は、独自言語を持っていて、その言語でガシガシ書いていくようです。スクリーンショット に “action main()” で始まるいかにもプログラムっぽいものがありますが、コレです。
ただ、アルファベットをすべて打ち込むわけではなく、カーソルがあるところの文脈にあわせてそこで使えるコマンドなどが表示されるのでそれをタップして行くという感じです。(インテリボタンと言うみたい)
たとえば チュートリアル (英文・PDF) では、まず Shake イベントを選びます。続いてこのイベントの中身をプログラミングするんですが、「media ボタンをタップ」「songs ボタンをタップ」「rand ボタンをタップ」「play ボタンをタップ」 と 4回タップするだけで 「保存されている曲をランダムに再生」 というコードが出来上がる、なんて感じです。

もちろん、作ったアプリはいつでも実行できますし、Pin すればスタートスクリーンに配置することもできます。
また、Publish すれば公開することもできます。公開したアプリは誰でも TouchDevelop で読み込んで実行することができますし、コードを編集することもできるようです。また、公開されているアプリは https://www.touchdevelop.com/ でも見ることもできますし、こんな風に コードの内容も丸見え状態になってます。

TouchDevelop をインストールすると最初からいくつかサンプルが入っていて、実行したりコードを編集したりできます。これを書きながらちょこちょこと眺めてみましたが、なかなか興味深いです。

2011年12月21日水曜日

[WP7] PhoneGap が Windows Phone 7.5 に完全対応

PhoneGap が 1.3 で Windows Phone 7.5 に完全対応したそうです。
Full Support for PhoneGap on Windows Phone is Now Complete!

PhoneGap は HTML5+CSS3+JavaScript フレームワークで、これを使えば iOS や Android などのマルチプラットフォーム対応アプリケーションを作成することができます。(と言っても、私は使ったこと無いですし、ぜんぜんわかってないですが)
HTML5 と言っても Web サイト上のアプリではなく、出来上がるのはクライアントアプリです。
WP7 の場合は .xap ファイルが出来上がります。(.xap の中に HTML5、CSS3、JavaScript などのファイルも含まれています)
なので、普通のアプリと同様にマーケットプレース経由で配布することになります。

Get Started with PhoneGap on Windows Phone 7
こちらのブログには紹介動画もありました。
PhoneGap をインストールすると Visual Studio 2010 用のプロジェクトテンプレートも入るようです。これでプロジェクトを新規作成すると一通り必要なものは自動作成されます。あとは HTML なり CSS なり JavaScript なりをガシガシ書いていくだけです。

一本目の紹介動画を見ると、navigator.notification.alert(“メッセージ”); なんてやるとちゃんと WP7 風のメッセージボックスが表示されてます。(ソース見たわけじゃありませんが、HTML で擬似的に作ってるんじゃなく、WebBrowser コントロール経由で本物の MessageBox を呼び出してるんじゃないかと思います)
console.log(“ログ出力”); なんてやると Visual Studio の 「出力」 に出力されます。(これは System.Diagnostics.Debug.WriteLine を呼び出してるのかな)

二本目の動画では、カメラを呼び出してます。
カメラは navigator.camera.getPicture() で呼び出せるようですが、どうやらデフォルトではカメラはサポートされていない様子。
と言っても、サポートするのは簡単で、PhoneGap に Camera.cs というソースが含まれているのでそれをプロジェクトの Plugins フォルダに追加するだけ。サイズをコンパクトにできるようにプラグイン方式にしているんでしょうね。

2011年12月20日火曜日

[WP7] エミュレーターでもラジオのテストができる

Windows Phone Arch 主催の Windows Phone Hackathon in Osaka (12/4 開催) のときに 「FM ラジオってエミュレーターでは鳴らせませんよねぇ」 という話をしていたら 「いや、鳴らすことできますよ」 と教えてもらいました。

エミュレーターでも周波数 88.5 もしくは 89.5 にすれば音楽が流れるようになってるんですね。88.5 と 89.5 ではちゃんと違う曲が流れます。もちろん本物のラジオが鳴るわけではなく、エミュレーターに埋め込まれた音楽が鳴るだけですが。
コードで書くと

Microsoft.Devices.Radio.FMRadio.Instance.Frequency = 88.5;

これだけでエミュレーターから音楽が鳴り始めます。

しかし、この情報ってどこに書いてあるんだろ?MSDN Library を検索してみましたがどこに書いてあるのかわかりませんでした。

2011年12月14日水曜日

[Live] SkyDrive API

まだよく読んでませんがちょっと覚え書き。

SkyDrive APIs for Docs and Photos—now ready to cloud enable apps on Windows 8, Windows Phone and more

もともと含まれていたのか、それとも今回追加されたのかはよくわかりませんが、最近リリースされた Live SDK 5.0 には SkyDrive だとかカレンダーだとかにアクセスするクラスが含まれているようですね。それだけでなく、REST で SkyDrive にアクセスする方法なんかも公開されているみたい。

Windows Phone 用の公式 SkyDrive アプリもリリースされましたが、Live SDK を使えば SkyDrive 対応アプリを作るのも簡単そう。

# 実は一番驚いたのは Live SDK のサンプル を見ようと思ったらサンプルの公開に github が使われてることだったり。
# Microsoft 公式で、Download Center とか CodePlex とかでなく github が使われてるのなんて初めて見た。

2011年9月28日水曜日

[WP7] @IT:たった30分で完成。初めてのWindows Phone 7.5アプリ開発

@IT に記事が掲載されました。
たった30分で完成。初めてのWindows Phone 7.5アプリ開発

「WPFやSilverlightでの開発経験がある方に向けて、Windows Phoneでのアプリケーション開発がどのようなものかを紹介」という内容です。よろしければぜひご一読ください。

2011年6月30日木曜日

[WP7.1] Beta2 のリリースノートに書かれてることで気になったところ

今朝から Windows Phone SDK 7.1 Beta2 がダウンロードできるようになったようで一部で盛り上がってますが、とりあえず Release Notes を見てみました。
しっかり読んだわけじゃありませんが、ちょっと気になったところを覚え書き。

Known Issues のところ

  • Controls のところ、「マルチラインの TextBox は “\r\n” の代わりに改行として “\r” を使う」
  • Silverlight and XNA Framework のところ、「XNA Framework レンダリングしている ListBox は正しくスクロールしない。ScrollViewer.ManipulationMode=”Control” を付けると解決する」

これらってそのうち直るってことなんだろうか?それともこのまま?

Breaking Changes のところ

  • 最初にある 「ScrollViewer と ListBox の入力処理が UI スレッドじゃなくなった」 というのは 「[WP7] Mango で ListBox や ScrollViewer のパフォーマンスが向上する」 ここで書いたやつですね。
  • 次に 「画像のデコードは UI スレッドではなく、バックグラウンドスレッドで実行される」 なんてあります。ちょっとでも UI スレッドを軽くしようということですね。けど、「Caution: This change will be reverted in a future release. 」 なんて注意書きが。しかも、「You should not make any changes to your application code.」 なんてことまで。(この変更は将来のリリースで元に戻される。なので、あなたのコードを書き換えたりしないこと)良かれと思ってやってみたけど、イマイチだったから元に戻すってことなのかな?
  • その次には 「非同期 web client リクエストのレスポンスはバックグラウンドスレッドで動く」 なんてあります。今までこのあたりは非同期ではあるけど UI スレッドも使っている (詳しく調べてませんが、確か UI スレッドをブロックしてると WebClient からのレスポンスも返ってこなくなってたような) という感じでしたが、完全に別スレッドで動くようになるってことでしょうか?

[WP7] WebBrowser コントロール (WP7.0)

Windows Phone 7 の WebBrowser コントロールについてのもろもろ
注意: 以下は 7.1(Mango)ではなくすべて 7.0 の情報です。7.1 では IE9 ベースに変わってるので WebBrowser コントロールもいろいろと変わってるんじゃないかと思います。それらについてはまだまったく調べてません。

■ NavigateToString() メソッドで日本語表示
NavigateToString() メソッドで日本語を表示しようとすると化けます。内部では utf-8 に変換していないのに utf-8 で渡しちゃってるとかそんな感じなのかな?
とりあえず 「International UTF-8 Characters in Windows Phone 7 WebBrowser Control」 にあるように文字実体参照にして渡せば化けずに表示できます。

■ Data URI scheme は未サポート
Data URI scheme っていうやつ (HTML の中に <img src=="data:image/png;base64,ここにBASE64の文字列”> なんて書くやり方)について。
仕様については↓にあります。
data Protocol (MSDN Library)
The "data" URL scheme (RFC2397)
残念ながら NavigateToString() メソッドでこの書式の HTML を書きこんでも画像は表示されません。(×印になってしまう)
検索してみたら、このやり方ができるようになったのは IE8 からだそうです。で、WP7 の IE は 7+ くらいだからそもそもサポートしてないんじゃね?ということらしいです。
ということは、WP7.1(Mango) ではできるようになってるかも(未確認)

■ WebBrowser コントロールのリファレンス
WP7 の WebBrowser コントロールのドキュメントは↓
WebBrowser Control for Windows Phone
けど、ほとんど何も書いてないな。

■ WebBrowser コントロールから HTML 内の JavaScript を呼び出す
WebBrowser.InvokeScript() メソッドで HTML 内の JavaScript メソッドを呼び出すことができます。
(ただし、事前に IsScriptEnabled = true にしておく必要あり)
たとえば、HTML 内に func() という名前の関数があった場合には

this.webBrowser1.InvokeScript("func”);

といった感じです。
関数に引数がある場合は this.webBrowser1.InvokeScript("func”, “abc”, “あいう”); でいけました。(この場合、日本語も化けませんでした)

■ HTML 内の JavaScript からの呼び出しを WebBrowser コントロールのイベントで受け取る
WebBrowser.ScriptNotiry イベントで HTML 内の JavaScript から呼び出しをイベントとして受け取ることができます。
HTML 内に <input type="button" onclick="window.external.Notify('button1 click')" value="click"/> なんてのがあった場合、

this.webBrowser1.ScriptNotify += webBrowser1_ScriptNotify;

private void webBrowser1_ScriptNotify(object sender, NotifyEventArgs e)
{
    MessageBox.Show(e.Value);
}

という感じです。

■ 拡大縮小できないようにする
Web ブラウザーなので拡大縮小できてしまいますが、これは <head> に

<meta name="viewport" content="width=200"/>
<meta name="viewport" content="user-scalable=no"/> 

を入れておくと禁止できるようです。

2011年6月27日月曜日

[Silverlight] Silverlight を囲む会 in 大阪 #19 に参加しました

Silverlight を囲む会 in 大阪 #19 に参加してきました。
今回のメインテーマは SharePoint。
SharePoint MVP でもあり、SharePoint をメインに扱う会社の代表取締役でもある山崎さんをスピーカーに迎えて。
私自身は SharePoint のことはほとんど初心者レベルだったので、初めて知るようなことが多く、いろいろとおもしろかったです。
Silverlight Web パーツの開発のお仕事なんてできるとおもしろそう(残念ながら今のところ SharePoint を使っているという人(個人・法人)の心当たりがまったくありませんが)

また、30分ほどのショートセッションでしたが、マイクロソフトのエバンジェリストである大西さんの Windows Phone 7 Mango の紹介。
休憩時間中に実機もさわらせてもらいました。
あぁ、Mango が楽しみ。

伊勢シンさんの 「Socketプログラム Siverlight for Windows Phoneへの移植のポイント」 もおもしろかった。
伊勢シンさんは 「誰得だよ」 とおっしゃってましたが、私にとっては結構 「俺得」 でしたw

最後にいろいろなプレゼントの抽選会。
先週の VSUG DAY 2011 Summver 東京 の際にマイクロソフトの高橋忍さんから 「大阪で勉強会があったときにでも配ってください」 と Windows Phone 開発技術情報 DVD と WP-Arch シールを頂いていたのでそれも希望者に配布しました。DVD は 20枚くらいあったので余ると思ってたんですが、品切れになっちゃいました。ということは、ほぼ全員が持って帰ったってことですね。やっぱり、直前に大西さんに Mango 実機を見せてもらってるし、みんな興味を持ったのかもしれませんね。

その後はお楽しみの懇親会。
その後、大西さんを交えての二次会、さらに三次会と楽しい一日でした。

2011年6月16日木曜日

[WP7] Mango で ListBox や ScrollViewer のパフォーマンスが向上する

Listbox – ScrollViewer performance improvement for Mango and how it impacts your existing application?
こちらの記事より。

「Outlook とかの標準アプリ(Windows Phone 7 に標準で入っているアプリ) のぬるぬるさに比べると、俺らのアプリいまいちなんだけど」 という声がそれなりにあったということでしょうか?ListBox のぬるぬるさが足りないというフィードバックが結構あったようで Mango では入力関係の入力スレッド、アニメーション関係のコンポジタースレッド、アイテム生成の UI スレッドに分けて処理することによって ListBox や ScrollViewer のパフォーマンスが向上するそうです。

ただ、そのために若干動作が異なる部分が出てくるみたい

  • ScrollViewer でスクロールしているときのプロパティの更新(UI スレッド上)
    • WP7 上の 7.0 アプリ
      プロパティが変化するとすぐさま更新
    • Mango 上(7.0 アプリと 7.1 アプリの両方)
       a. 指を離したとき
       b. 任意の方向にスクリーンの 1/4 以上ドラッグ、パン、フリックしたとき
      にプロパティが更新される
  • ScrollViewer の中でドラッグして Manipulation Delta イベントが発生するのは (UI スレッド上)
    • WP7 上の 7.0 アプリ
      ScrollViewer の中にあるエレメントによってハンドルされるこれが可能
    • Mango 上(7.0 アプリと 7.1 アプリの両方)
      入力スレッド上のイベントなので ScrollViewer によって飲み込まれる。スクロールしているときに不必要なイベントを発生しないようにするというパフォーマンス向上の一環

この非互換性が困ると言う場合は、どうやら

<ListBox ItemsSource="{Binding Items}" ScrollViewer.ManipulationMode ="Control" Height="652" Canvas.Top="80">

と言う風に ScrollViewer.ManipulationMode ="Control" を付けることができるようです。
ただし、これはまったくお勧めしない方法ということみたい。

もうちょっとましな方法は、ScrollViewer の中に横スクロールする TextBlock を組み込むとかそういう風にコードを書き換えることだそうです。
ちょっと詳しいことは読み取れてませんが、きっと縦スクロールは ScrollViewer のまかせてぬるぬるに、横スクロールはパノラマみたいにちょっとしか必要ないことが多いだろうからそっちは TextBlock とかを使って従来のスクロールにする、というような意味じゃないかと思います。横方向にたくさんのスクロールが必要な UI っていうのは普通は無いでしょうからね。

で、最後に、当然ながら ScrollViewer や ListBox を使ってない場合はなにも変わらないとあります。
たとえば、Silverlight for Windows Phone 7 Toolkit に入っている LongListSelector とかは効果なしだそうです。
えっ?と思って LongListSelector の XAML を見てみたら、これって Canvas に自前で描画してるみたいですね。誰か ScrollViewer を使う形に書きなおしてくれないかなぁ。

[.NET] スレッドセーフな ObservableCollection<T> が欲しい

Windows Phone 7 のコードを書いていると今まで以上に UI スレッドをブロックしたくなくなるんですよね。(ぬるぬるにしたいからw)

で、今更ながらに ObservableCollection<T> についてどうにかならないか考えてたんですが、どうにもなりそうにないですねぇ。
ObservableCollection<T> は INotifyCollectionChanged を実装してコレクションに変更があったことを通知してくれるようになってるわけですが、この INotifyCollectionChanged の CollectionChanged イベントは 「何番目の要素が変更されたか」 といった情報も伝えるようになってます (NotifyCollectionChangedEventArgs 参照)。で、CollectionChanged イベントを受け取るのは ListBox などの UI 要素であることが多いわけです。必ずしもそうと決まっているわけではないですが、ObservableCollection<T> を使うのは ListBox などの ItemsSource にしたいから、という場合がほとんどじゃないかと思います。そして、ListBox などの UI 要素のほとんどの機能は UI スレッド以外から呼び出すことはできません。呼び出すと例外が発生します。そのため、CollectionChanged イベントも UI スレッド以外で発生させるのは危険ということになります。
ObservableCollection<T> に対して Insert や Remove などを行うと自動的に CollectionChanged イベントが発生するわけですから、結局のところ UI スレッド以外でこういったコレクションの内容を変更することはできないわけです。もちろん、Insert や Remove の処理自体は別スレッドで行って、CollectionChanged イベントの発行のみ UI スレッドでやるという実装も可能ですが、CollectionChanged イベントの呼び出しが終わるまでコレクションの内容が NotifyCollectionChangedEventArgs の内容と整合性が取れていることを保証しなくちゃいけませんから、結局のところあんまり別スレッドで Insert、Remove などの処理を行う意味は無いって感じになってしまいます。

ObservableCollection<T> 単体で考えればスレッドセーフにする意味があるかもしれませんが、ListBox の ItemsSource にデータバインディングしている ObservableCollection<T> と考えると ListBox の中身まで含めて都合をつけなくちゃいけないのでどうにも手の出しようがないって感じですね。
こういう風に考えると、この記事のタイトルは 「スレッドセーフな ObservableCollection<T> が欲しい」 ではなくて、「UI 要素に任意のスレッドからアクセスできるようにして欲しい」 というところに行き着いちゃうわけです。

「ObservableCollection threadsafe」 で検索するとすぐに Thread safe observable collection この記事が見つかりました。
見てみると、これもやはりほとんどのメソッドを Dispatcher 経由で UI スレッドにスイッチしてますね。参照系は ReaderWriterLock で別スレッドからでもアクセス可にしてあるので、その部分はパフォーマンス向上に繋がるかもしれませんが、それくらいかなぁ?
あと、この例では Dispatcher.Invoke() メソッドを使って UI スレッドに同期的にスイッチしていますが、Silverlight/WP7 には Invoke() は無いんですよねぇ。(BeginInvoke() しかありません)
Dispatcher.BeginInvoke() を使って非同期的に UI スレッドにスイッチするとなると、上にも書いたように UI スレッド側での CollectionChanged イベントの呼び出しが終わるまでコレクションの内容を維持してやるとかいった仕組みが必要になります。(CollectionChanged イベントの呼び出しが終わるまで次の Insert や Remove の実行をブロックするとか) そういう実装もやれないことは無いですが、あんまりパフォーマンスは良くならないような感じがしちゃいます。

と、言うわけで、この件は考えるのやめましたw
何かいいアイデアがあったら教えてください。

2011年6月9日木曜日

[WP7] 起動ページを MainPage.xaml 以外にする

Visual Studio のテンプレートで Windows Phone 7 のプロジェクトを作ると、起動ページとして MainPage.xaml が指定されています。
これを他の xaml に変更するには、Properties フォルダの下の WMAppManifest.xml にある

<Tasks>
    <DefaultTask  Name ="_default" NavigationPage="MainPage.xaml"/>
</Tasks>

ここを書き換えれば OK です。

まぁ、それなりに WP7 開発をやってる人にとっては常識なのかもしれませんが、私はちょっと悩んじゃいましたw
始めは、「App.xaml か App.xaml.cs あたりに書いてあるんだろう」 と思って見てみてもそれらしいものは無し。「じゃあ、プロジェクトの設定なのか?」 とプロジェクトのプロパティや、.csproj ファイルを直接テキストエディターで見てもそれらしいものは無し。結局、grep して見つけました。

2011年6月8日水曜日

[WP7] ListBox のデータの仮想化

Windows Phone 7 の ListBox はデフォルトでも VirtualizingStackPanel を使います。そのおかげで、見えている部分+α 程度の要素だけを生成します。
要するに、1万行ある ListBox でも最初にいきなり 1万行作るわけではなく、見えている部分の 10行ちょっと程度だけ作ることによって高速化してくれるわけです。
ただこれはビジュアル要素(TextBlock やら Border やらのこと)についてです。
データについては、1万行だったらあらかじめ 1万行分必要です。
それを、最初に 1万行分作らなくても済むようにしようというのが「データの仮想化」です。

Virtualizing Data in Windows Phone 7 Silverlight Applications
この記事によると IEnumerable では無く IList を継承したクラスを ItemsSource にセットすることで、必要になったデータのみを取得するようになってくれるようです。
ちなみに、必要なのは Count、IndexOf、this[] の get のみでそれ以外は NotImplementedException を投げるようにしとくだけでも構わないようです。

で、さっそく試してみみても常に全件取得されちゃってなぜかまったく仮想化されず悩みました。
ふと気付いて試してみてわかりましたが、ItemTemplate が無いと仮想化されないんですね。

<ListBox>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

このようにほとんど意味が無くても ItemTemplate は必須みたいです。

これで試してみると、最初にだいたい 100件程度分 this[] が呼び出されて、あとは ListBox をスクロールすると必要に応じて適当に this[] が呼び出されるという感じです。
もちろん、IList ではなく IList<T> を継承したクラスでも問題無く仮想化されました。

というか、IList と IEnumerable の両方を継承している場合はちゃんと仮想化されるようです(IList の方が優先されてる)。
なので、List<T>、ObservableCollection<T>、普通の配列など、いずれも大丈夫なんじゃないかと。
ダメなのは IEnumerable、もしくは、IEnumerable<T> しか無い場合です。
この場合は、GetEnumerator() が呼び出されて最初に全件取得されます。

というわけで、普通にコレクションクラスを使ってる時は自然とデータの仮想化も使ってることになりそうです。
IEnumerable しか無いっていうと、一番ありそうなのは LINQ 関連のことをやってる場合ですね。

public IEnumerable<Data> GetItemsSource()
{
    for (var i = 0; i < 10000; ++i)
    {
        yield return new Data(i);    // ←このデータを作るのが重い処理
    }
}

こんなメソッドがあって、これを ListBox.ItemsSource に渡してるとか、
もっと直接的に

this.ListBox.ItemsSource = from i in Enumerable.Range(0, 10000)
                           select new Data(i);    // ←このデータを作るのが重い処理

こんな風なことをしてると、1万個の Data クラスのインスタンスが出来上がるまで UI が固まってしまいます。(Data クラスの中身が string がいくつかあるだけとかなら、1万個くらい一瞬で出来上がっちゃうかな。そういう場合はほとんど気にする必要は無いと思いますが)
LINQ を使ってると、便利なんでついつい 「from なんちゃら~」 で済ませてしまおうとしちゃいがちなのでちょっと気をつけた方がいいかも。(と、自分に対して言っておくw)

2011年6月6日月曜日

[Silverlight][WP7] DependencyProperty.RegisterReadOnly が無い

すごく今さらですが、Silverlight・Windows Phone 7 には DependencyProperty.RegisterReadOnly() メソッドが無いんですね。
うーむ。
探してみたら
Sometimes you just gotta do the best you can [Tip: Read-only custom DependencyProperties don't exist in Silverlight, but can be closely approximated]
こんな記事はありましたが。。。
SetValue されたときに元の値に戻して例外を発生させるという力業。。。つか、ちっとも ReadOnly じゃないじゃん。
RegisterReadOnly() メソッドくらい用意しておいてくれてもよかったような。

2011年5月30日月曜日

[WP7] ScrollViewer のスクロールに反応する

Windows Phone 7 の ScrollViewer (確認してませんが、Silverlight や WPF でも同じかも) にはスクロールしたことを伝えるイベントがありません。
けど、スクロール量を表す HorizontalOffset、VerticalOffset プロパテイがあります。
ならば、これらにデータバインディングしてやればスクロールしたときにあわせて処理をできるんじゃないかと。

public static readonly DependencyProperty MyVerticalOffsetProperty =
    DependencyProperty.Register("MyVerticalOffset", typeof(double), typeof(MyView), new PropertyMetadata(0.0, MyVerticalOffset_PropertyChanged));

private static void MyVerticalOffset_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
    // ScrollViewer.VerticalOffset が変わったときにここが呼ばれる
}

こんなのを用意しておいて、あとは

XAML で書くなら
<ScrollViewer VerticalOffset="{Binding MyVerticalOffset, Mode=TwoWay}" />

コードで書くなら
var binding = new Binding("MyVerticalOffset") { Source = this, Mode = BindingMode.TwoWay };
this.ScrollViewer.SetBinding(ScrollViewer.VerticalOffsetProperty, binding);

こんな感じでいいのかなぁ?と。

がっ!これはできないんですね。
ScrollViewer.VerticalOffset プロパティなんかは readonly なので、実行時に例外が発生してしまいます。
BindingMode.OneWayToSource にしてやればよさそうにも思えますが、Silverlight には OneWayToSource がありません。
というわけで、どうもこのアプローチはダメみたいです。

しかし、添付プロパテイであれば相手が readonly でも添付できるようです。

private static int verticalOffsetAttachedPropertyCounter = 0;

// コンストラクタ
public MyView()
{
    InitializeComponent();

    // ScrollViewer.VerticalOffset に添付プロパティをアタッチして変化を検出する
    var property = DependencyProperty.RegisterAttached("MyVerticalOffset" + verticalOffsetAttachedPropertyCounter, typeof(double), typeof(MyView), new PropertyMetadata(0.0, MyVerticalOffset_PropertyChanged));
    ++verticalOffsetAttachedPropertyCounter;
    var binding = new Binding("VerticalOffset") { Source = this.ScrollViewer };
    this.ScrollViewer.SetBinding(property, binding);
}

private void MyVerticalOffset_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
    // ScrollViewer.VerticalOffset が変わったときにここが呼ばれる
}

こんな感じでうまくいきました。
上記ではインスタンス上で RegisterAttached してますが、もちろん、普段の依存関係プロパティのように static に RegisterAtached しても構いません。
その場合、当然 MyVerticalOffset_PropertyChanged() メソッドも static にすることになります。
今回、static ではなくインスタンスでやっているのは MyVerticalOffset_PropertyChanged() メソッドに渡される DependencyObject が添付先(今回の場合だと ScrollViewer)になっちゃうからです。依存関係プロパティのときはここに自分が渡されるのでキャストすれば自分のインスタンス変数にアクセスできますが、添付プロパティだと自分にアクセスするすべがなくなっちゃいます。そんなわけで static ではなくインスタンスにしています。

ただ、これ、インスタンスが作られるたびに RegisterAttached してるわけですが、いいのかな?まぁ、UnregisterAttached みたいな解除するための API が無いのでどうしようも無いんですが。