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 я не хватает.