I am working on my first project in MVVM and I've chosen to use the MVVM Light Toolkit. I have a GameViewModel
that handles business on the main screen of my game. I need to find out how to open a new window (AdventurerView
) with an instance of Adventurer
as a parameter when a command is executed, have it bound to AdventurerViewModel
, and display and return data. Instances of this window will be opened and closed frequently. I have been stuck on this for a couple of days now and it's driving me crazy. I would like to learn how to do this in an MVVM-friendly way, preferably with the tools provided by MVVM Light or pure XAML.
I've tried using MVVM Light's ViewModelLocator
but since AdventurerView
is a window it won't work; it says "Can't put a Window in a Style", though the program still compiles and runs. Could there be something I could change to make that work? Or is there another way to bind them in XAML? Or another approach entirely? I would really love to be able to move on from this. I have also tried using MVVM Light's messenger to no avail (which still doesn't tackle the View/ViewModel issue).
I just need to be able to create a window that is bound to AdventurerViewModel
and display/return the appropriate data.
AdventurerView.xaml is in its default state at the moment, but I feel that if I could bind the appropriate data that might help (DataContext).
AdventurerViewModel is pretty bare-bones as well
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 with the non-working DataTemplate at the bottom:
<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>
The command in GameViewModel
that will hopefully make this all happen (the messagebox just confirms that the command is firing):
private void ExecuteShowAdvCommand(Adventurer adv)
{
System.Windows.MessageBox.Show(adv.Name);
}
I don't really know what else to include.
Messenger
that comes with mvvm-light? In simple terms you firstly do NOT declare a new window as aDataTemplate
in your MainWindow's xaml. What you do is in theGameViewModel
when you need to create yourAdventureView
send a message toMainWindow
which should register and receive this message in the code-behind, create theAdventureView
and callShow()
orShowDialog()
on that appropriately.SimpleIoC
should be handling the creation of the VM forAdventureViewModel
. Does this make sense to you? – NumerationMessenger
to send the results back to theGameViewModel
– NumerationMessenger.Default.Send<T>()
whereT
can be any type you want. so you can create a class call itMyMessage
and to send a message with this object you'd just doMessenger.Default.Send<MyMessage>(new MyMessage(){ SomeProp = "Some Val"});
– NumerationMessenger.Default.Register<MyMessage>(this, (args) => /* Do something with args parameter */);
In this example I'm assumingMyMessage
class has a string property calledSomeProp
. MVVM Light comes with a few message types built in. Have a look in this post galasoft.ch/mvvm under Messenger section – Numeration