用户控件很棒。您将一个易于使用(最好的情况下)的组件放在一起,以便在您的项目中重用。有时,您甚至将该控件放入(可移植的)类库中以使其跨平台可用。大多数用户控件都是在没有 MVVM 的情况下编写的,仅使用 DependencyProperties 和匹配的代码隐藏文件。
但是 – 可以创建一个带有自己的 ViewModel 的用户控件,只保留代码中的 DependencyProperties。对于由控件视图生成的值,存在一些限制。如果不创建对它的引用,就无法将它们放入 ViewModel(在某些人看来这可能会破坏 MVVM 模式)。好吧,有些人会争辩说“谁在乎,我需要让它工作,所以我得到了对 DataContext 的引用。”这没关系,但在我看来还有另一个更优雅的解决方案。一个监听那些的类更改值,将它们拉入您的 ViewModel——所谓的信使。
你们中的一些人可能使用过 MVVMLight、Prism 或类似的框架/工具包。如果你想在类库中使用它们,你会发现一些障碍,比如缺少 ViewModelLocator 等等。在工作中,我正在为我们的 LOB 应用程序开发通用用户控件。由于该控件涉及其视图中的许多值,因此我需要一种智能且快速的方法来将这些值放入我的 ViewModel 中。我用我自己的简单信使实现了它,使我能够避免我控制的任何框架/工具包。
我是这样做的。首先我创建了一个新的 Singleton 类 。如果您不知道单例是什么,只需单击前面句子中的链接即可。长话短说:Singleton 使类成为静态的,并确保所有其他类都在使用一个实例(以最终获得正确的值)。提示:可能由于时机不对,您仍然有多个实例。在这种情况下,您应该查看对 Singleton 实例的调用的不同实现方式。
在我的例子中,我使用的是简单的实现,如果没有,它会自动创建第一个实例:
public class SimpleMessenger
{
private static SimpleMessenger _instance;
public static SimpleMessenger Instance => _instance ?? (_instance = new SimpleMessenger());
}
下一步是创建一个 EventHandler,它会在 SimpleMessenger 有新值时通知我们。创建您自己的 EventArgs 以传递给 EventHandler 是绝对有意义的。只需收集您想要在派生自 EventArgs 的类中提供的数据,并使 EventHandler 使用此类作为其事件数据:
public class SimpleMessenger
{
private static SimpleMessenger _instance;
public static SimpleMessenger Instance => _instance ?? (_instance = new SimpleMessenger());
}
此类中最重要的功能是引发事件:
public class SimpleMessenger
{
private static SimpleMessenger _instance;
public static SimpleMessenger Instance => _instance ?? (_instance = new SimpleMessenger());
}
我只使用了三个所需的基本值:更改的属性的名称、旧值和更新后的值。这已经使我能够在 View 和 ViewModel 之间发送数据,甚至可以发送到我无法控制的范围内。当然,您想了解如何使用我的 SimpleMessenger 发送“消息”。这也很简单。
首先,您需要获取对当前实例的引用:
public class SimpleMessenger
{
private static SimpleMessenger _instance;
public static SimpleMessenger Instance => _instance ?? (_instance = new SimpleMessenger());
}
要发送数据,只需使用 RaiseMessageValueChanged 事件:
public class SimpleMessenger
{
private static SimpleMessenger _instance;
public static SimpleMessenger Instance => _instance ?? (_instance = new SimpleMessenger());
}
最后但同样重要的是,我们还可以在其他地方读取这些值:
public class SimpleMessenger
{
private static SimpleMessenger _instance;
public static SimpleMessenger Instance => _instance ?? (_instance = new SimpleMessenger());
}
如您所见,使用此类以解耦方式获取值很简单(就像 MVVM 模式所要求的那样)。当然,您仍然需要注意不要过度使用它。例如,我正在使用它来获取我的控件在 ViewModel 中具有的 DependencyProperties 的更改值(否则只能通过引用它才能实现)。
这个 SimpleMessenger 可能不如流行的框架/工具包中的功能强大,但对于在用户控件或小型应用程序中使用它应该非常适合。我附上了一个非常简单的项目来演示 SimpleMessenger。只需启动项目,然后使用鼠标调整应用程序窗口的大小。它会将根网格的大小写入控制台。
一如既往,我希望这篇文章对你们中的一些人有所帮助。