6

我正在开发我的第一个 MVVM 项目,我选择使用 MVVM Light Toolkit。我有一个GameViewModel在我的游戏主屏幕上处理业务的。我需要了解如何在执行命令时AdventurerView以 的实例Adventurer作为参数打开一个新窗口 ( ),将其绑定到AdventurerViewModel,并显示和返回数据。此窗口的实例将经常打开和关闭。我已经坚持了几天了,这让我发疯了。我想学习如何以对 MVVM 友好的方式执行此操作,最好使用 MVVM Light 或纯 XAML 提供的工具。

我尝试过使用 MVVM Light ViewModelLocator,但因为AdventurerView它是一个窗口,所以它不起作用;它说“不能在样式中放置一个窗口”,尽管程序仍然可以编译和运行。有没有什么我可以改变的东西来完成这项工作?还是有另一种方法可以在 XAML 中绑定它们?或者完全是另一种方法?我真的很想能够从此继续前进。我也尝试过使用 MVVM Light 的 Messenger 无济于事(仍然无法解决 View/ViewModel 问题)。

我只需要能够创建一个绑定到AdventurerViewModel并显示/返回适当数据的窗口。

AdventurerView.xaml 目前处于其默认状态,但我觉得如果我可以绑定可能有帮助的适当数据(DataContext)。

AdventurerViewModel 也很简单

class AdventurerViewModel : ViewModelBase
{
    #region Members

    private Adventurer _adv;

    #endregion

    #region Properties

    public Adventurer Adv
    {
        get { return _adv; }
        set { _adv = value; }
    }

    #endregion

    #region Construction

    public AdventurerViewModel(Adventurer adv)
    {
        this._adv = adv;
    }

    #endregion
}

App.xaml 底部有非工作 DataTemplate:

<Application StartupUri="MainWindow.xaml"
         xmlns:views="clr-namespace:AoW.Views"
         xmlns:vm="clr-namespace:AoW.ViewModels" 
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         x:Class="AoW.App" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         mc:Ignorable="d">

<Application.Resources>
    <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />

    <DataTemplate DataType="{x:Type vm:GameViewModel}">
        <views:GameView />
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:TitleViewModel}">
        <views:TitleView />
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:AdventurerViewModel}">
        <views:AdventurerView />
    </DataTemplate>

</Application.Resources>
</Application>

其中的命令GameViewModel有望使这一切发生(消息框只是确认命令正在触发):

    private void ExecuteShowAdvCommand(Adventurer adv)
    {
        System.Windows.MessageBox.Show(adv.Name);
    }

我真的不知道还要包括什么。

4

2 回答 2

23

好的,我整理了一个演示,希望对您来说更容易下载链接

功能:

  • 共 3 个窗口 ( MainWindow, ModalWindow, NonModalWindow)
  • MainWindow有一个TextBox你可以输入任何你想要的东西。
  • 顶部的 2 个按钮将相应地打开模态/非模态窗口
  • 每个窗口打开时都会在其中显示 MainWindowTextBox中的消息TextBlock
  • 在每个窗口中,您可以勾选 aCheckBox以更新结果文本块中的值MainWindow(对于模态窗口,这将在模态窗口关闭时启动。对于非模态变化可以尽快看到)

功能就是这样,

概念:

  • 向 注册多个 VMSimpleIoC并使用GetInstance(...)来请求它们。
  • 使用自定义消息类型的 Messenger 类使用OpenWindowMessage
  • 从遵循 MVVM 原则的父 VM 打开模态/非模态窗口
  • 在窗口之间传递数据(仅显示在 NonModal 中)

重要说明: - 本示例中用于DialogResult从模态窗口设置非 DP 的方法不是 MVVM 友好的,因为它使用代码隐藏来设置避免的事件的DialogResult属性(如果需要“可测试”)。我的首选方法有点长,并且在此处有很好的记录(问答混合)。因此,为什么我为了这个样本而忽略了它。Window.Closing

于 2013-06-07T23:50:13.577 回答
1

跟进 Viv,我修改了示例以包含一个不使用代码打开窗口的示例。

示例项目在这里。

我正在使用带有静态方法的 ViewModelLocator 单例,该方法更新视图模型、窗口和数据上下文,而不是后面的代码。

带有详细信息的博客文章。 让我知道哪种方法更可取。我不喜欢在后面使用代码,但我可能会遗漏一些优点和缺点。

于 2013-09-05T20:38:39.537 回答