gpt4 book ai didi

c# - 从 View 发送消息到 ViewModel : what is an appropriate token?

转载 作者:行者123 更新时间:2023-11-30 17:50:16 25 4
gpt4 key购买 nike

让我们定义:

  • 一个 viewModel:TabViewModel
  • View :TabView

我有 nTabView 类实例,所以有 nTabViewModel 实例。当 TabView 类的一个实例发送一条消息时,我希望它被它自己的 View 模型接收,并且只有这个

据我了解 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);

这对我来说似乎是“mvvm 友好的”,因为 View 不知道什么是 DataContext。但是使用这个解决方案,我担心内存泄漏:在 mvvm light 中,收件人是弱引用的,但 token 不是(正如您将在 WeakActionAndToken struct of the Messenger class 中看到的那样。

我可以使用什么作为 token ? viewmodel 实例是否是一个好的选择,如果使用它如何防止内存泄漏?


编辑:可能的解决方案

选项 1(基于道德逻辑答案):

  1. 在 View 和 View 模型上定义 token 属性(例如字符串或 GUID 类型)
  2. 定义其中之一的值(唯一值,例如在 View 模型的构造函数中设置它)
  3. 在 XAML 中将它们绑定(bind)在一起
  4. 在 Messenger 通话中使用它们

选项 2(我采用的那个):

使用viewmodel实例作为Token。

为了防止内存泄漏,我们必须将它封装在一个weakReference中。为了与比较 2 个标记的 Messenger 一起工作,weakReference 应该实现 Equals 方法(这不是 WeakReference 的默认 .Net 实现的情况)类)。

所以我们有:

// 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);
}
}

优点是在 View 和 View 模型上都是轻量级代码,没有内存泄漏。测试成功。如果您有更好的解决方案,请随时发表评论。

最佳答案

Token 是 View 传递给 ViewModel 的对象唯一值,它们都使用相同的 Token。喜欢

View

public partial class MainWindow : Window
{
readonly string Token;
public MainWindow()
{
Token = Guid.NewGuid().ToString();
InitializeComponent();
DataContext = new MainViewModel(Token);
}
}

ViewModel

public class MainViewModel 
{
readonly string Token;

public MainViewModel(string token)
{
Token = token;
}
}

实际上 Token 背后的逻辑是,当我们向 Messenger 注册一个委托(delegate)时。它确实有内部字典,并且此 Token 充当该字典中的键。 View 及其 ViewModel 必须具有相同的 token ,以便可以在 Send 方法上触发与该键对应的确切委托(delegate)。

关于c# - 从 View 发送消息到 ViewModel : what is an appropriate token?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20922165/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com