MVVM Light & WPF - привязка Несколько экземпляров окна для ViewModel

Я работаю над своим первым проектом в MVVM, и я решил использовать MVVM Light Toolkit. У меня есть GameViewModel, который обрабатывает бизнес на главном экране моей игры. Мне нужно узнать, как открыть новое окно (AdventurerView) с экземпляром Adventurer в качестве параметра при выполнении команды, привязать его к AdventurerViewModel и отобразить и вернуть данные. Экземпляры этого окна будут часто открываться и закрываться. Я застрял на этом пару дней, и это сводило меня с ума. Я хотел бы узнать, как это сделать с помощью MVVM-friendly, желательно с инструментами, предоставляемыми 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);
    }

Я не знаю, что еще включить.

Ответ 1

Хорошо, я собрал демоверсию, которая должна сделать это, надеюсь, проще для вас Ссылка для скачивания

Функциональность:

  • 3 Windows в Total (MainWindow, ModalWindow, NonModalWindow)
  • MainWindow имеет TextBox, вы можете ввести все, что хотите.
  • 2 кнопки вверху откроют окно Modal/NonModal соответственно.
  • Каждое открытое окно отображает сообщение, которое было в MainWindow TextBox, в TextBlock внутри них.
  • В каждом окне вы можете отметить CheckBox, чтобы обновить значение в текстовом блоке результата в MainWindow (для модального окна это произойдет, когда модальное окно будет закрыто. Для изменений NonModal можно увидеть как можно скорее)

Что это за функциональность,

Основные понятия:

  • Регистрация нескольких виртуальных машин с помощью SimpleIoC и использование GetInstance(...) для их запроса.
  • Использование класса Messenger с настраиваемым типом сообщения OpenWindowMessage
  • Открытие модальных/немодальных Windows из родительской VM, остающейся верной принципам MVVM.
  • Передача данных между окнами (как показано в NonModal)

Важное примечание:  - Метод, используемый в этом примере для установки не DP DialogResult из модального окна, не совместим с MVVM, потому что он использует код для установки свойства DialogResult в событии Window.Closing, которое должно следует избегать (если нужно быть "проверяемым" ). Мой предпочтительный подход немного длинный и очень хорошо документирован ЗДЕСЬ (Смесь вопросов и ответов). Поэтому я проигнорировал это ради этого образца.

Ответ 2

Следуйте за Viv, я изменил образец, чтобы включить пример открытия окна, не используя код позади.

Пример проекта здесь.

Я использую Singleton ViewModelLocator со статическим методом, который приводит в новостях вверху viewmodel и окна и Data Context вместо кода.

Сообщение в блоге с подробностями. Позвольте мне знать, какой метод является предпочтительным. Мне не нравится использовать код позади, но может быть про и con я не хватает.