【问题标题】:WPF & MVVM Light- Pass object into new windowWPF & MVVM Light- 将对象传递到新窗口
【发布时间】:2013-06-01 19:12:22
【问题描述】:

我想了解最合适的方法:我的 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 友好的东西。

任何建议将不胜感激。

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

游戏视图模型:

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 方法,但 Prism 和 MVVM Light 之间存在一些冲突,导致的麻烦多于其价值。我对任何与 MVVM Light 和一般 MVVM 模式兼容的想法持开放态度。

更新:另外,如果可能的话,我想以一种可以同时存在多个弹出窗口的方式来做到这一点。

【问题讨论】:

    标签: c# wpf xaml mvvm mvvm-light


    【解决方案1】:

    在类似的情况下,我使用了 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.
        }
    }
    

    【讨论】:

    • IEntityViewModel 到底是什么?我一直在四处寻找,但没有找到任何有关它的信息。
    • 它不是任何框架的一部分,只是我用来将视图与视图模型分开一点的接口。编辑我的问题以包含一个示例...
    【解决方案2】:

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

    【讨论】:

    • 这看起来是我在这种情况下采取的最佳途径。一旦我得到它的工作,我会接受你的回答。这对我来说是全新的,所以可能需要一点时间。
    • @DennisE 是的,我花了一点时间才让一切正常运行。好消息是你不需要一个成熟的 Prism 应用程序。您可以只使用 InteractionRequest 对象。祝你好运,如果您有任何问题,请告诉我。
    • 您发布的链接中的代码充满了错误,无法编译,但我确实找到了这个示例,它似乎可以满足我的所有需求:codeproject.com/Articles/269364/… - 该示例包括许多类和我想知道我需要那些来实现我想要做的事情(即显示有关对象的信息并可能发回更新的数据)。如果你不介意帮我解决这个问题,也许我们可以开始聊天?
    • 我刚刚下载了相同的示例,它对我来说构建得很好。你得到什么错误?我现在不能聊天。检查参考并确保它找到了所有内容。下载包含您需要的所有文件。你提供给我的那个链接很相似,但我认为更复杂。
    • 我得到了你发布的样本(我只需要从 NuGet 购买 Prism),它看起来很有希望。我将在今天晚些时候开始将 prism 集成到我的项目中。
    【解决方案3】:

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

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

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

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

    【讨论】:

    • [...] 正确的 MVVM 不会实例化视图并通过构造函数传递视图模型。 - 嗯,为什么这不正确?我知道ViewViewModel 之间的唯一限制是,View 可以知道ViewModel,但ViewModel 必须不知道View
    • 正确的 mvvm 将视图与视图模型分离,因此它们之间没有直接依赖关系。
    • 如果某个实体引用了它的属性(绑定),它怎么能与实体分离呢? - O.o
    • 这就是 WPF 的强大之处——它是基于属性的绑定,而不是特定的类型绑定,这意味着您可以将任何对象与这些属性绑定并让它针对视图工作。
    猜你喜欢
    • 2015-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-20
    • 1970-01-01
    相关资源
    最近更新 更多