我使用 Caliburn.Micro。好吧,说实话,这是我面临的整个问题:
我在设计时设置了绑定(bind)。请看下面的代码:
<Window x:Class="Microtech.TPM.Views.DestinationChoiceView"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"
xmlns:vmns="clr-namespace:Microtech.TPM.ViewModels"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=vmns:DestinationChoiceViewModel, IsDesignTimeCreatable=True}"
cal:Bind.AtDesignTime="True" Width="1280" Height="1024">
<Window.Resources>
<vmns:DestinationChoiceViewModel x:Key="ViewModelKey" />
</Window.Resources>
我需要订阅 ViewModel 的事件。如果我在 Window.Resources 中定义了对 ViewModel 的引用并将其用于 xaml 中的进一步绑定(bind),如何实现这一点?我完全不明白如何使用相同的引用。此外,我完全不明白这段代码已经拥有多少个 ViewModel 实例。据我了解,我至少会有 2 个实例,对吗?那么,如何避免这种情况呢?这是问题的一部分。
最佳答案
如果您正在执行 ViewModel-First 绑定(bind),您应该已经使用了 Bootstrapper
类为您的应用程序层次结构创建 Root View 模型。
在这种情况下,您需要绑定(bind)到包含 ViewModel
的属性。它位于您的根虚拟机上,或者您需要将虚拟机设置为 Conductor
和 Activate
其中的一项或多项。
示例 - 将其他虚拟机绑定(bind)为属性
你的虚拟机:
public class RootViewModel : PropertyChangedBase
{
private SomeOtherViewModel _someOtherView;
public SomeOtherViewModel SomeOtherView
{
get { return _someOtherView; }
set
{
if(_someOtherView != value)
{
_someOtherView = value;
NotifyOfPropertyChange(() => SomeOtherView);
}
}
}
}
以及相关的 View :
<Window x:Class="SomeProject.SomeView">
<... some view related code - buttons etc ...>
<!-- Render the other ViewModel using CMs conventions -->
<ContentControl x:Name="SomeOtherView">
</Window>
示例 - 使用导体
虚拟机:
public class RootViewModel : Conductor<IScreen>
{
public RootViewModel(SomeViewModel someViewModel)
{
ActivateItem(someViewModel);
}
}
以及相关的 View :
<Window x:Class="SomeProject.SomeView">
<... some view related code - buttons etc ...>
<!-- Render the other ViewModel using CMs conventions -->
<ContentControl x:Name="ActiveItem">
</Window>
除了上述之外,我的建议是不要将 View 模型声明为资源,因为您正在 View 中创建对该 VM 的依赖项。您还分散了对引用定位和处理的关注,并将其传播到您的 View 中,这可能会导致维护问题和意大利面条式代码。
请记住,您希望将类的复杂性降至最低,因此您的类应遵循单一职责原则 - 即它们应该关注一个功能领域,而不应该负责该单一范围之外的工作。这就是我们拥有 IoC 容器的原因,它们在那里管理您的引用(作为一个组件,这是他们的单一职责!)
IoC 容器
SimpleContainer
Caliburn Micro 附带的适用于大多数项目;添加一个流行的 IoC 容器(例如 CaSTLe Windsor/Ninject 等)很容易,并且有很多教程可以让它运行这样,您可以在 VM 中指定所需的依赖项,但对这些依赖项的解决和控制不可知
为了在你的虚拟机之间发送事件和消息,CM 有两种机制:
例如
<Window x:Class="SomeProject.SomeView">
<Button cal:Message.Attach="[Event Click] = [Action ButtonClicked()]">click me</Button>
</Window>`
(这将在您的 ViewModel 上调用 ButtonClicked() 方法)
IHandle<T>
来监听特定类型的消息在哪里 T
是您感兴趣的消息类型我要指出的是, View 或虚拟机在任何时候都不会相互引用——尽管有可能,除非真的有必要,否则应该避免。 View 模型应该完全不知道 View ,对象之间没有耦合。 Caliburn Micro 可以将 VM 粘合到 View 上,它在这方面做得很好。
对象越解耦,就越容易进行(不可避免的)更改、重构和添加。
如果您在使用 CM 时遇到困难,我建议您浏览 CodePlex 网站上的所有教程
http://caliburnmicro.codeplex.com/wikipage?title=Basic%20Configuration%2c%20Actions%20and%20Conventions&referringTitle=Documentation
关于wpf - 是否可以使用 ViewModel 第一种方法从 View 订阅 ViewModel 事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18566192/