定義しましょう:
- viewModel :
TabViewModel
クラス - ビュー :
TabView
クラス
私はクラスのインスタンスをn 個持っているので、. クラスの 1 つのインスタンスがメッセージを送信するとき、それを独自のビューモデルで受信したいのですが、この 1 つだけです。TabView
TabViewModel
TabView
mvvm light ツールキットの Messenger を理解しているので、次のようなものを使用する必要があります。
// in the view
Messenger.Default.Send(new RefreshMessage(/*...*/), oneToken);
と
// in the viewmodel
Messenger.Default.Register<RefreshMessage>(this, oneToken, MyViewModelMethod);
何に使えばoneToken
いいですか?
私が最初に考えたのは、ViewModel インスタンスを token として使用することでした。
// in the view
Messenger.Default.Send(new RefreshMessage(/*...*/), this.DataContext);
と
// in the viewmodel
Messenger.Default.Register<RefreshMessage>(this, **this**, MyViewModelMethod);
ビューはDataContextが何であるかを知らないため、これは私には「mvvmフレンドリー」に思えます。しかし、このソリューションでは、メモリ リークが心配です。mvvm ライトでは、受信者は弱参照されますが、トークンはそうではありません ( Messenger クラスの WeakActionAndToken 構造体でわかるように) 。
トークンとして何を使用できますか? ビューモデル インスタンスは適切な選択ですか? また、それを使用した場合にメモリ リークを防ぐにはどうすればよいですか?
編集:可能な解決策
オプション 1 ( ethicallogicsの回答に基づく):
- ビューとビューモデルの両方でトークン プロパティ (文字列型や GUID 型など) を定義します。
- それらのいずれかの値を定義します(一意の値、たとえばビューモデルのコンストラクターで設定します)
- それらを XAML でバインドする
- メッセンジャー通話で使用する
オプション2(私が取ったもの):
viewmodel インスタンスをトークンとして使用します。
メモリ リークを防ぐには、weakReference にカプセル化する必要があります。2 つのトークンを比較する Messenger を操作するには、weakReference にEquals
メソッドを実装する必要があります (これは、クラスのデフォルトの .Net 実装の場合ではありませんWeakReference
)。
だから私たちは持っています:
// in the view
Messenger.Default.Send(new RefreshMessage(), new EquatableWeakReference(this.DataContext));
と
// in the viewmodel
Messenger.Default.Register<RefreshMessage>(this, new EquatableWeakReference(this), ApplyRefreshMessage);
EquatableWeakReference
次のようにクラスを実装しました:
/// <summary>
/// A weak reference which can be compared with another one, based on the target comparison.
/// </summary>
public class EquatableWeakReference : IEquatable<EquatableWeakReference>
{
private WeakReference reference;
private int targetHashcode;
public EquatableWeakReference(object target)
{
if (target == null)
throw new ArgumentNullException("target");
reference = new WeakReference(target);
targetHashcode = target.GetHashCode();
}
public override bool Equals(object obj)
{
return Equals(obj as EquatableWeakReference);
}
/// <summary>
/// As Equals is overriden, we must provide an override for GetHashCode.
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return targetHashcode;
}
public bool Equals(EquatableWeakReference other)
{
if (other == null
|| !reference.IsAlive
|| !other.reference.IsAlive)
return false; // we assume that if both references are not alive, the result is inconclusive : let's say false.
return this.reference.Target.Equals(other.reference.Target);
}
}
アドバンテージは、ビューとビューモデルの両方で軽量なコードであり、メモリ リークがありません。テストに成功しました。より良い解決策があれば、コメントしてください。