MVVM Light - 将项目选择传递给ViewModelSeletor

时间:2013-09-24 21:04:26

标签: mvvm windows-phone-8 windows-phone mvvm-light

最新的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属性

1 个答案:

答案 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开箱即用。