WPF& MVVM Light-将对象传递到新窗口

时间:2013-06-05 22:22:10

标签: c# wpf xaml mvvm mvvm-light

我想学习最合适的方法:我的GameView中有一个Listview绑定到ObservableCollection<Adventurer>。双击单元格后,我需要一个新窗口(或其他任何更合适的东西),根据单元格打开并显示有关正确Adventurer的数据。到目前为止,我还没有。这就是我到目前为止所做的事情(它并不多,但我尝试过的任何工作都没有。)

GameView.xaml

中ListView中的触发器/命令
<i:Interaction.Triggers>
    <i:EventTrigger EventName="MouseDoubleClick">
        <cmd:EventToCommand Command="{Binding Mode=OneWay, Path=ShowAdvCommand}"
                            CommandParameter="{Binding ElementName=AdvListView, 
                                                       Path=SelectedItem}"
                            PassEventArgsToCommand="True" />
    </i:EventTrigger>
</i:Interaction.Triggers>

GameViewModel.cs中的命令

ShowAdvCommand = new RelayCommand<Adventurer>(p =>
{
    System.Windows.MessageBox.Show(p.Name);
});

MessageBox就是为了确认Eventtocommand正在运行。

我基本上需要一个容器,在双击Listview单元格后允许我显示特定于该实例的数据,该容器将接受正确的Adventurer作为参数。我也更喜欢坚持MVVM友好的东西。

非常感谢任何建议。

更新:我可能取得了一些进展:

GameViewModel:

ShowAdvCommand = new RelayCommand<Adventurer>(p =>
{
    AdventurerView adv = new AdventurerView(p);
    adv.Show();
});

AdventurerView:

public partial class AdventurerView : Window
{
    Adventurer adv;

    public AdventurerView(Adventurer adv)
    {
        this.adv = adv;
        InitializeComponent();
    }
}

现在我需要弄清楚如何在XAML,数据绑定等方面做到这一点。

更新: ...然后我意识到这完全违背了MVVM。有人有什么建议吗?

更新:MVVM Light的使者会帮我吗?我一直在修补它但没有让它起作用。

更新:这个问题仍悬而未决。我尝试了棱镜方法,但Prism和MVVM Light之间存在一些冲突,造成了比它值得更多的麻烦。我对任何与MVVM Light和MVVM模式兼容的想法持开放态度。

更新另外,我想以多种弹出窗口可以同时存在的方式执行此操作。

3 个答案:

答案 0 :(得分:4)

在类似情况下,我使用过MvvmLight的Messenger,它运行得非常好。双击,从包含要传递的实体的viewmodel发送消息。在某处您需要注册才能接收消息,具体取决于您设置视图的方式和要激活的视图模型。

您可以注册以在MainPage.xaml中接收消息,并将实体直接传递给视图的构造函数,或者通过接口访问视图的DataContext以传递实体,具体取决于您是否使用了viewmodel你的孩子窗口。 E.g。

AdventurerView adv = new AdventurerView();
IEntityViewModel vm = adv.DataContext as IEntityViewModel;
vm.SetCurrentEntity(entity);
adv.Show();

IEntityViewModel可能如下所示:

public interface IEntityViewModel<T> where T : class
{
    void SetCurrentEntity(T entity);
}

viewmodel将实现此接口:

public class AdventurerViewModel : IEntityViewModel<Adventurer>
{
    public void SetCurrentEntity(Adventurer entity)
    {
        // Do what you need to with the entity - depending on your needs, 
        // you might keep it intact in case editing is cancelled, and just
        // work on a copy.
    }
}

答案 1 :(得分:0)

正如您所指出的,正确的MVVM不会实例化视图并通过构造函数传递视图模型。你最好将ViewModel绑定到View,并且有很多不同的方法。

已出现的一种模式是称为“屏幕导体”的概念。这是一个顶级ViewModel或控制器,用于处理哪个ViewModel代表主窗口。同样,许多不同的方法来做到这一点。例如,ViewModel可以引发Screen Conductor处理的标准.net事件。您可以使用消息传递系统,如Caliburn.Micro的EventAggregator或MVVM Light的Messenger。我认为MEFedMVVM也有一个事件聚合器来完成这个任务。

Caliburn.Micro还有一个WindowManager,你可以在ViewModel中传递它,让它自动找到相应的View并管理窗口的生命周期。

很多选择。找到最适合你的那个。

答案 2 :(得分:0)

这是Prism的InteractionRequest的一个很好的例子。实质上,您在ViewModel上有一个InteractionRequest对象,当您双击(在双击命令中)时,您会引发该对象。您的视图上有一个Action,用于处理Raised事件并显示新视图。您将新的ViewModel传递给该交互,这是将显示的窗口的DataContext。 Here's some good information让你入门这就是我在应用程序中显示所有子窗口的方式。