2013年1月29日火曜日

【WinRT】ユーザーコントロールのリソース開放


一つ前のポスト,一回修正を行った.
なぜかというとユーザーコントロールのリソース開放に失敗していたからだ.

既に修正済みなので元がどうであったかはそちらを見ても分からないが,
具体的にはデストラクタでリソース開放を行おうとしていた.

こんな感じである.
よくよくOtherClass_EventOccurredメソッド内でログを吐かせてみるとイベントの解除ができていなかった.
ページを切り替えても残っているのである.

WinRTのコントロールにおいてリソースを開放するためには
デストラクタではなく,Unloadedイベントを使うこと
これ重要.
デストラクタは呼ばれない.

WPFではUnloadedではなくDiposedイベントなのだろうか.
触ったことないのでそこはわからない.

というわけで,上記のを修正したのがこうなる.

あぶないあぶない.
WinRTはやはりなかなかノウハウがないな.

【WinRT】XAMLエディタでナゾのObject Null Reference

年末年始と特に問題なく進んできたので
ここに来るのも久しぶりである.
久しぶりに躓いた.
…とてつもなくしょうもないことなのだが.

WinRTでボタンをカスタムする.
表示と同時に別のクラスのイベントを登録し,
イベントが上がるごとにボタンの表示・非表示を変えたい.

適当にクラスを作ったが,OtherClassがイベント(EventOccurred)を上げてくると
OtherClass_EventOccurredメソッドが呼ばれ,
その中でViewChangeを呼び,ボタン自身の表示を切り替える.

つまり,イベントが起こるごとに表示/非表示を切り替えるボタンができた.

さて,このカスタムUIの使用方法は
XAMLエディタで
<local:CustomButton x:Name="playListButton" HorizontalAlignment="Right" />
このような感じである.
通常のButtonタグを
local:CustomButtonタグに変えただけだ.

しかしここで問題が起こる.

XAMLのlocal:CustomButtonタグの行に
Delegate to an instance method cannot have null 'this'.
もしくは
Object reference not set to an instance of an object
というエラーが発生する.

内容としては
インスタンスメソッドへのデリゲートにnullを指定できねえよ
とか
オブジェクトに何もセットされてねえよ
とかそういう意味だと思うが
それでもよく分からん.

しかし,ビルドすると通る.
配置もできて実行もされる.
すなわちランタイムでは問題が起きない.


ここで答え合わせ.

実はこのエラーは(多分)XAMLデザイナーが影響を受けたエラー.
ランタイムでは起きない.
VisualStudioのXAMLデザイナーでプレビューを表示させようとしたときに
OtherClass.Instanceというインスタンスが発見できず,
VisualStudio「おい,このインスタンスnullじゃねえか」
ということになってるんだと思う.

言ってしまえばUIコントロールに他のクラスのインスタンスを参照したのが原因.
XAMLデザイナーはそこまで見ずにプレビューを作成する.

しかし,実際にビルドすると通り,なおかつ動作に影響しないのは,
ランタイムではOtherClassクラスのインスタンスを生成しており,
CustomButtonクラスから参照できるからである.

実動作に問題がなければいいといえばいいのだが,
エラー一覧欄にWarningはもとより,Errorが表示されっぱなしというのは
精神衛生上よろしくない.

ここまで書くと解決法は簡単だと思うが,
このように変更するとエラー一覧欄から消えてくれる.


OtherClassのインスタンス,_instanceを参照する前に
それが存在するかどうか確認して,存在しなければreturnする処理を追加しただけ.

こういったリッチなエディタにはランタイムは問題なくデザイナーに起因するエラーというものが起こりがちである.
eclipse + Android SDKでもあるあるである.
UI周りでどっからどう考えてもおかしくないのにエラーが消えないという場合は
このようにデザイナーを疑ってみるのもいいかもしれない.