最新的MVVM Light工具包使用ViewModelLocator(VML)中的IoC来提供ViewModel的实例。
这些实例由只读实例属性(即非静态)提供
示例显示从VML公开的MainViewModel,但不显示父视图子视图
我的主视图正在查看MainViewModel公开的人员列表。
当在主视图中点击其中一个Person项时,我想导航到PersonView。 PersonView将绑定到PersonViewModel。
PersonViewModel会从VML公开吗?如果是这样,MainViewModel会做什么来传达PersonViewModel的点击?它无法在VML中设置PersonViewModel,因为该属性只是一个Get。
我过去使用过MVVM Light,并在VML上使用了Ready Write属性
答案 0 :(得分:0)
这是一个使用MVVM Light Messenger Class的确切情况。您首先要使用VML注册您的人员视图,就像您的MainView已链接
一样将此添加到ViewModelLocator构造函数:
SimpleIoc.Default.Register<PersonViewModel>();
在构造函数外部添加它(使用代码片段mvvmlocatorproperty):
/// <summary>
/// Gets the PersonView property.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public PersonViewModel PersonView
{
get
{
return ServiceLocator.Current.GetInstance<PersonViewModel>();
}
}
并确保您的视图如此连接:
<Window x:Class="MvvmLight1.PersonView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ignore="http://www.ignore.com"
mc:Ignorable="d ignore"
DataContext="{Binding PersonView, Source={StaticResource Locator}}">
现在,在ListBox ItemTemplate
上连接一个Event to Command <i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseUp">
<cmd:EventToCommand Command="{Binding OpenPersonCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
确保在XAML窗口decleration中包含这两个名称空间:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
现在你们都迷上了使用定位器。
就消息传递而言,要打开新视图,您需要创建消息。下面是我的视图模型,我将在
后解释public class MainViewModel : ViewModelBase
{
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel()
{
OpenPersonCommand = new RelayCommand(() =>
{
Messenger.Default.Send<Person>(new Person() { FirstName = "Daryl" }, "OPENPERSONVIEW");
});
}
/// GOT THIS USING mvvminpc snippet
/// <summary>
/// The <see cref="OpenPersonCommand" /> property's name.
/// </summary>
public const string OpenPersonCommandPropertyName = "OpenPersonCommand";
private ICommand _openPersonCommand;
/// <summary>
/// Sets and gets the OpenPersonCommand property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public ICommand OpenPersonCommand
{
get
{
return _openPersonCommand;
}
set
{
if (_openPersonCommand == value)
{
return;
}
RaisePropertyChanging(OpenPersonCommandPropertyName);
_openPersonCommand = value;
RaisePropertyChanged(OpenPersonCommandPropertyName);
}
}
}
}
确保包含GalaSoft.MvvmLight.Command,GalaSoft.MvvmLight.Messaging以使其正常工作。你正在做的是向收到那种类型的消息(在这种情况下是一个Person对象)的任何人发送一条消息,带有那个确切的令牌(在这种情况下,我的令牌是一个字符串“OPENPERSONVIEW”,第二个参数。我通常使用枚举器,但这只是为了简单起见。
现在,在MainView.xaml的代码中,在构造函数中添加它:
Messenger.Default.Register<Person>(this, "OPENPERSONVIEW", (myPerson) =>
{
PersonView view = new PersonView();
view.ShowDialog();
Messenger.Default.Send<Person>(myPerson, "PASSVARIABLE");
});
我们所做的是我们已经注册以接收使用Person对象传递的任何消息,并且具有“OPENPERSONVIEW”标记。一旦我们在Code Behind中收到该消息,我们就会实例化一个新的PersonView。一旦该人员视图被实例化,我们将发送另一条带有我们的Person对象的消息,该消息只会被正在侦听令牌“PASSVARIABLE”的Messenger侦听器接收。
现在,要将主视图模型中的实际值转换为您的人物视图模型,您将使用另一个信使来接收使用令牌“PASSVARIABLE”发送的消息。在PersonViewModel的构造函数中,添加:
Messenger.Default.Register<Person>(this, "PASSVARIABLE", (myPerson) =>
{
ThisPerson = myPerson;
});
并确保在视图模型中使用名为ThisPerson的属性(使用MVVM Light中的mvvminpc片段创建):
/// <summary>
/// The <see cref="ThisPerson" /> property's name.
/// </summary>
public const string ThisPersonPropertyName = "ThisPerson";
private Person _thisPerson;
/// <summary>
/// Sets and gets the ThisPerson property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public Person ThisPerson
{
get
{
return _thisPerson;
}
set
{
if (_thisPerson == value)
{
return;
}
RaisePropertyChanging(ThisPersonPropertyName);
_thisPerson = value;
RaisePropertyChanged(ThisPersonPropertyName);
}
}
基本上,我们所做的是使用MVVM Light Messenger类来传递数据,但它们都是松散耦合的。没有一个注册的Messegers关心传递给他们的内容,或者他们是谁,只是在听他们的令牌,并做他们所要求的。
我知道这很长,但请发表评论,我会一步一步地遇到问题。我刚刚发现很多MVVM Light问题的答案会告诉我们一小部分,但不是整个画面。
还有其他方法可以做到这一点,但这是基本的MVVM-Light开箱即用。