2

我想了解最合适的方法:我的 GameView 中有一个 Listview 绑定到ObservableCollection<Adventurer>. 双击单元格后,我需要一个新窗口(或其他更合适的窗口)来打开并Adventurer根据单元格显示正确的数据。到目前为止,我一直无法。这就是我到目前为止所拥有的(数量不多,但我尝试过的都没有奏效)。

我的 ListView 中的触发器/命令GameView.xaml

<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 正在工作。

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

任何建议将不胜感激。

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

游戏视图模型:

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

冒险家视图:

public partial class AdventurerView : Window
{
    Adventurer adv;

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

现在我需要弄清楚如何在 XAML、数据绑定等中进行这项工作。

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

更新: MVVM Light 的信使会在这里帮助我吗?我一直在修补它,但还没有让它工作。

更新:这个问题仍然悬而未决。我尝试了 Prism 方法,但 Prism 和 MVVM Light 之间存在一些冲突,导致的麻烦多于其价值。我对任何与 MVVM Light 和一般 MVVM 模式兼容的想法持开放态度。

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

4

3 回答 3

5

在类似的情况下,我使用了 MvvmLight 的 Messenger,效果非常好。双击时,从您的视图模型中发送一条消息,其中包含您要传递的实体。您需要在某个地方注册才能接收消息,具体取决于您如何设置要激活的视图和视图模型。

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

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.
    }
}
于 2013-06-06T02:01:03.270 回答
0

这是 Prism 的 InteractionRequest 的一个很好的案例。本质上,您的 ViewModel 上有一个 InteractionRequest 对象,当您双击时(在您的双击命令内)会引发该对象。您的视图上有一个 Action 处理 Raised 事件并显示新视图。您将一个新的 ViewModel 传递给该交互,这就是将要显示的窗口的 DataContext。这里有一些很好的信息可以帮助您入门。这就是我在应用程序中显示所有子窗口的方式。

于 2013-06-06T02:38:49.380 回答
0

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

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

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

很多选择。找到最适合您的。

于 2013-06-06T02:08:18.277 回答