MVVM Light& WPF - 将Window的多个实例绑定到ViewModel

时间:2013-06-07 21:43:52

标签: c# wpf mvvm mvvm-light

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

我尝试过使用MVVM Light的ViewModelLocator,但由于AdventurerView是一个窗口,它不起作用;虽然程序仍在编译和运行,但它说“不能把窗口放在一个样式中”。我可以改变一些东西让它起作用吗?或者是否有另一种方法在XAML中绑定它们?或完全是另一种方法?我真的很想能够继续前进。我也试过使用MVVM Light的信使无效(仍然没有解决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);
    }

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

2 个答案:

答案 0 :(得分:23)

好的,我整理了一个演示版,可以让您更加轻松Download Link

<强>功能

  • 3个Windows总计(MainWindowModalWindowNonModalWindow
  • MainWindowTextBox您可以输入任何内容。
  • 顶部的2个按钮将相应打开模态/非模态窗口
  • 打开时,每个窗口都会显示MainWindow中TextBoxTextBlock内的消息。
  • 在每个窗口中,您可以勾选CheckBox以更新MainWindow中结果文本块中的值(对于模态窗口,当模态窗口关闭时,这将启动。对于非模态更改,可以看到asap )

这就是功能性,

<强>概念

  • 使用SimpleIoC注册多个VM并使用GetInstance(...)将其请求退出。
  • 使用自定义消息类型OpenWindowMessage
  • 的Messenger类使用情况
  • 从坚持MVVM原则的父虚拟机打开模态/非模态Windows
  • 在窗口之间传递数据(仅在NonModal中显示)

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

答案 1 :(得分:1)

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

Sample project is here.

我正在使用ViewModelLocator单例和一个静态方法来预告视图模型和窗口以及数据上下文而不是后面的代码。

Blog Post with Details. 让我知道哪种方法更可取。我不喜欢使用背后的代码,但可能会有专业人士和骗局我不知道。