スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: スポンサー広告

いつか必ず後始末(壱)

Windows.Formsにかぎらず、WPFでも、イベント機能を使用する。専用の構文(event)で宣言されたイベントに対し、「+=」でリスナとなるメソッドを登録し、「-=」でリスナとなるメソッドを削除する。Javaの世界では有名なGOFのObserver パターンに似ているだろうか。
public class AAAA {
public event EventHandler TawamureDrived;
}

あるいは、
public class AAAA {
private EventHandler tawamureDrived_;

public event EventHandler TawamureDrived {
add {tawamureDrived_ += value;}
remove {tawamureDrived_ -= value;}
}
}

という感じで定義する。
WPFの依存関係プロパティという機能でも、このイベントとは切れない関係にあった。依存関係プロパティに設定した値が変化した時に、それをトリガーとして、イベントにメソッドを登録する。
MVVMパターンで、イベントをどうにかしよう。
でも書いた、Loadedイベントとコマンドを連携させるときなんかが典型となる。上の記事では特に書いていないが、いつか必ず後始末をする必要がある。前にそれをネタにちょっと書いた事がある。
添付プロパティの注意点
イベントへのメソッド登録は、そのメソッドを持つクラスのインスタンスを参照するという事と同じ意味になる。「そのインスタンスを参照するオブジェクトが消えない限り、ガベージコレクトされる事はない」ので、結局それが残り続け、メモリリークの元となる。
frwElement.Loaded += new RoutedEventHandler(FrwElement_Loaded);
としたのであれば、どこかで
frwElement.Loaded -= new RoutedEventHandler(FrwElement_Loaded);
とする必要がある。イベントを持つインスタンスとメソッドを持つインスタンスが事なる時は特にだ。タイミング的には、「ウィンドウが閉じられた時」だと思っているので、WindowクラスのClosedイベントにメソッドを登録してイベントを削除するようにしている。
/// <summary>
/// Loadedイベントハンドラ用メソッド
/// </summary>
/// <param name="sender">イベント発生元</param>
/// <param name="e">イベント引数</param>
private static void FrwElement_Loaded(object sender, RoutedEventArgs e) {
//Loadedイベントを持つのは、FrameworkElement継承くらすのみ。
var frwElement = sender as FrameworkElement;
var window = Window.GetWindow(element);//親ウィンドウを取得する。

if (window != null) {

Action<object, EventArgs> closedHandler = null;

closedHandler = (sender2, e2) => {
//こうしないと、Loadedイベントに登録したメソッドの削除ができない
frwElement.Loaded -=
new RoutedEventHandler(FrwElement_Loaded);

if (closedHandler != null) {
window.Closed -= new EventHandler(closedHandler);
closedHandler = null;
}
};

window.Closed += new EventHandler(closedHandler);
}
}
このやり方にも少々問題がある。
・添付プロパティ1つ1つに対して、Loadedイベントを登録する必要があるので、メソッドが重複しないように苦心する必要がある(主にメソッド名)。
・Loadedイベントからのメソッド削除、Closedイベントからのメソッド削除は、言わば「お約束」で、同じようなコードがそこかしこにできることになる。
・UnloadedやLoadedが何回も発生するような実装では、↑の処理はちょっと直す必要がある。
・こういう処理を必ず書いてね、と通知しても、忘れる人はいる(それが意図的ではないにしても)。
こういう「切り貼り」できるようなコードは、共通化するのが一番だと思う。
つづく。
(追記)
WPFにおいて、Unloadedは、意外に簡単に発生する。一番手っ取り早いのは、Tabコントロール。
Tabの切り替えで、簡単にUnloaded←→Loadedが発生する。
スポンサーサイト
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0


この記事へのコメント

コメントの投稿

非公開コメント


サイドバー背後固定表示サンプル

当ブログに書かれたソースコードは流用自由です。

バグ、スペルミス等はありうる事です。

ご利用の際は自己責任でお願いしますm(_ _)m

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。