MVVM Light - Multiple ViewModels (and connecting them up) - c#

I am trying to learn the MVVM pattern (C#), having come from a Windows Forms background. I am using the MVVM Light toolkit, and so far I think it is brilliant.
I have made several small applications, however one thing I am struggling with is introducing a second view.
I want to (for example), have a button on my MainViewModel, which via a RelayCommand, opens up a new Window - let's say an "About" window. I have done hours of research on the web for this however it seems I can't get my AboutViewModel to communicate with/show my AboutView.
I have placed a receiving messenger in the code-behind constructor of the AboutView.xaml - however I can't get it to receive any messages from the AboutViewModel, and thus can't make it 'Show()'.
If anyone has an example of an Mvvm Light WPF app using multiple views that would be great :)

There are two ways I can think to do this easily
The first would be to use a Popup instead of a new Window. For example, I often put properties in my ViewModel for PopupContent and IsPopupVisible, and set those values anytime I want to display my Popup control. For example, a ShowAboutPopup relay command might run something like this:
void ShowAboutPopup()
{
PopupContent = new AboutViewModel();
IsPopupVisible = true;
}
You can display it using a Popup object, or a custom UserControl. I prefer to use my own custom Popup UserControl, which will usually end up looking like this:
<Window>
<Canvas x:Name="RootPanel">
<SomePanel>
<!-- Regular content goes here -->
</SomePanel>
<local:PopupPanel Content="{Binding PopupContent}"
local:PopupPanel.IsPopupVisible="{Binding IsPopupVisible}"
local:PopupPanel.PopupParent="{Binding ElementName=RootPanel}" />
</Canvas>
</Window>
The PopupContent property is a ViewModel (such as an AboutViewModel), and DataTemplates are used to tell WPF to draw specific ViewModels with specific Views
<Window.Resources>
<DataTemplate DataType="{x:Type local:AboutViewModel}">
<local:AboutView />
</DataTemplate>
</Window.Resources>
The other method is to have some kind of ApplicationViewModel that runs on startup, and is responsible for the overall application state, which includes which window(s) are open.
Typically I prefer to have a single ApplicationView that contains a ContentControl to display the current page
<Window>
<ContentControl Content="{Binding CurrentViewModel}" />
</Window>
however it can also be used to manage multiple windows. If you do use it to manage multiple Window objects, be warned that this will not be a pure ViewModel because it will need to access some View-specific objects, and referencing UI objects it not something a ViewModel should do. For example, it may subscribe to receive ShowWindow messages, and upon receiving those messages it would create the specified View and show it, and possibly hide the current window as well.
Personally, I try to avoid multiple windows as much as possible. My usual method is to have a single View that contains consistent application objects for any page, and a ContentControl containing dynamic content that changes. I have an example using this navigation style on my blog if you're interested

As i can see you want a navigation in your MVVM app?
Word goes to the creator of MVVM Light - Laurent Bugnion - with his post about using Navigation Service for switching Views. It's actually about Windows Phone & Silverlight but same should apply to WPF.
Also this answer in related question uses this approach.

Related

MVVM Displayer OberservableCollection<ViewModel> with unknown UserControl

im a little bit stuck with my current project and hope someone can help me out of this.
My application works with plugins so that the user is able to add additional functionality to the application. Now i would like to have the configuration window in the same style (Maybe a plugin need some kind of configurations).
The configuration window loads all plugins and get the configuration ViewModel from the plugins. All the ViewModels are stored in an ObservableCollection. These ViewModels should be displayed in a TabControl (one tab per ViewModel)
But i dont know the type of UserControl the plugin is using, because the plugin come up with its own UserControl for configuration purposes.
Otherwise i would create a TabControl, bind its ItemsSource to the ObservableCollection and specify the UserControl in the Resources (DataTemplates).
But how to do it in case the UserControls are unknown to compile time?
I thought about using a ObservableCollection instead of ViewModels, but im not realy happy with that and even dont know if this will work.
Do you have some idea how to deal with that?
Kind regards,
SyLuS
You could use a ContentControl to achieve this.
It's used to show views depending on their viewmodel.
In your xaml you can specifiy which view should be shown. Based on the viewmodel which is the current DataContext.
<ContentControl>
<ContentControl.Resources>
<DataTemplate DataType="{x:Type vm:MyViewModel}">
<v:MyView/>
</DataTemplate>
</<ContentControl.Resources>
</ContentControl>
But when you say you are using a plugin system, maybe something like PRISM, you have to setup the datatemplates automatically. Never done this before. But maybe I gave you a point where you can start.

Layouts with events and properties

How would I make an XAML layout which had bound properties and events? I'm going out of my mind.
First of all, it's for a chat application and a single room chat works fine, in the sense that I can design the layout of the application in XAML with name properties here there and everywhere in order to control it in C# but when it comes to repeating this layout multiple times because of multiple rooms, it becomes a bit of a problem. I was doing it solely by C# this lead to hundreds of lines of just defining controls and adding them to the window, and one problem with that would be the fact that name properties would collide.
I was going to go with modifying a ControlTemplate of a random control for example a Frame, but then I run into the issue of defining custom properties and events.
I just have no idea how I can do what I want to do. I've asked for help in many places to no avail.
I am honestly going out of my mind, and on the verge of giving up entirely.
My aim is to have a tabcontrol with multiple rooms, I need to be able to access controls in each room with ease so I can modify the content. I'm just getting no where.
Edit
Public chat template is obviously different to the private chat template, hence why I've failed so badly at this.
You can do it using MVVM pattern which is preferable when dealing with WPF.
However, this requires some experience and a lot of mind-warping.
Luckily, you can always use classic approach if you are coming from the Windows Forms world.
Just create an user control for the chat room which contains GUI, data, logic, event handlers, ...
Place instances of this chat room user control inside tab container and you are done.
Sounds like a perfect place for a data template!
First off, you need a "ChatRoom" class that contains all the state information for a given room. Then your main ViewModel needs to have a collection of these objects. Finally, set up your tab control with a DataTemplate that is probably nearly identical to your current window.
The TabControl would look like:
<TabControl ItemsSource="{Binding ActiveRooms}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
... (All your chat room stuff)
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
That way, whenever you create a new room (ActiveRooms should be an ObservableCollection, by the way) it automatically a new set of controls and binds them to the new room's instance properties.

MVVM Light & WPF - Binding Multiple instances of a Window to a ViewModel

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.
Ok I put together a demo that should make this hopefully easier for you Download Link
Functionality:
3 Windows in Total (MainWindow, ModalWindow, NonModalWindow)
MainWindow has a TextBox you can type whatever you want into.
2 buttons on the top will open the Modal / NonModal Window accordingly
Each window when opened will display the message that was in MainWindow's TextBox in a TextBlock inside them.
In each window you can tick a CheckBox to update the value in result's textblock in MainWindow (For the Modal Window this will kick in when modal window is closed. For NonModal changes can be seen asap)
That's it for functionality,
Concepts:
Registering Multiple VM's with the SimpleIoC and using GetInstance(...) to request them out.
Messenger class usage with a custom message type OpenWindowMessage
Opening Modal / Non Modal Windows from a parent VM staying true to the MVVM principles
Passing data between windows(just shown in NonModal)
Important Note:
- The method used in this example to set the non DP DialogResult from the modal window is not MVVM friendly cos it uses code-behind to set the DialogResult property on a Window.Closing event which should be avoided(If needing to be "testable"). My preferred approach is a bit long and is very well documented HERE(Mixture of question and answer). Hence why I ignored it for the sake of this sample.
Follow up to Viv, I modified the sample to include an example of opening the window without using a code behind.
Sample project is here.
I'm utilizing the ViewModelLocator singleton with a static method that news up the viewmodel and window and Data Context instead of the code behind.
Blog Post with Details.
Let me know which method is preferable. I dislike using code behind, but there could be pro's and con's I'm missing.

MVVM and View/ViewModel hierarchy

I'm working on making my first game using C# and XAML for Windows 8. I'm still learning the core concepts and best practices, and MVVM has been a hurdle. I'll attempt to ask the question in two parts.
Background
The game I'm making is Sudoku. Sudoku has a board that contains a 9x9 grid of tiles. I have three models - Game, Board, and Tile. When a Game is created, it automatically creates a Board, and when the Board is created, it creates 81 (9x9) Tiles.
1. With a hierarchy of views, how are corresponding view models created?
To match the hierarchy of models, I would like to have a hierarchy of views (GameView contains a BoardView which contains 81 TileViews). In XAML, it's pretty easy to create this hierarchy of views with user controls, but I don't understand how the view models get created.
In the examples I've seen, the data context of a user control is often set to the view model (using the ViewModelLocator as a source) which creates a fresh instance of the view model. This seems to work well if you have a flat view, but also seems like it gets messy when you have a hierarchy. Does the GameView create a GameViewModel and leave it up to its BoardView child to create a BoardViewModel? If so, how does the GameViewModel communicate with the BoardViewModel? Can the BoardViewModel communicate back up the hierarchy to the GameViewModel?
2. How does a view model get model data?
In iOS, I would start by using a service to fetch a Game model that was pre-populated with data. I would then create a GameViewController view controller (which was in charge of creating the view) and pass the Game to it. In MVVM, I see the value in having a view be in charge of creating its own view model (ideally using a ViewModelLocator), but I don't understand how that view model gets the model.
In all of the examples I've found online, the view model uses some service to fetch its own data. But I haven't come across any example that accepts constructor params or params passed from a higher level of navigation. How is this done?
I don't want to use an application resource or some other kind of singleton storage method for my model because, not that I do, but what if I wanted to display multiple puzzles on the screen at once? Each GameView should contain its own Game.
Not only does the GameViewModel need a reference to the Game model, but the BoardViewModel that was created somehow (see question 1) needs a reference to the Board model that belongs to the Game model. The same goes for all the Tiles. How is all this information passed down the chain? Can I do this much heavy lifting entirely within XAML, or am I going to have to do some sort of binding or other initialization in code?
Phew!
I appreciate any advice you can give, even if it's not a full answer. I'm also keen to find any examples of MVVM projects that share similar challenges to my own. Thanks a ton!
I would start by creating a class to begin the application with. Typically I call that class something like ApplicationViewModel or ShellViewModel, even though technically it can abide by different rules than what I would typically use for a ViewModel
This class gets instantiated at startup, and is the DataContext for the ShellView or ApplicationView
// App.xaml.cs
private void OnStartup(object sender, StartupEventArgs e)
{
var shellVM = new ShellViewModel();
var shellView = new ShellView();
shellView.DataContext = shellVM;
shellView.Show();
}
This is usually the only place I set a DataContext for a UI component directly. From this point on, your ViewModels are the application. Its important to keep this in mind when working with MVVM. Your Views are simply a user friendly interface that allows users to interact with the ViewModels. They're not actually considered part of the application code.
For example, your ShellViewModel may contain:
BoardViewModel CurrentBoard
UserViewModel CurrentUser
ICommand NewGameCommand
ICommand ExitCommand
and your ShellView might contain something like this:
<DockPanel>
<Button Command="{Binding NewGameCommand}"
Content="New Game" DockPanel.Dock="Top" />
<ContentControl Content="{Binding CurrentBoard}" />
</DockPanel>
This will actually render your BoardViewModel object into the UI as the ContentControl.Content. To specify how to draw your BoardViewModel, you can either specify a DataTemplate in ContentControl.ContentTemplate, or use implicit DataTemplates.
An implicit DataTemplate is simply a DataTemplate for a class that doesn't have an x:Key associated with it. WPF will use this template anytime it encounters an object of the specified class in the UI.
So using
<Window.Resources>
<DataTemplate DataType="{x:Type local:BoardViewModel}">
<local:BoardView />
</DataTemplate>
</Window.Resources>
will mean that instead of drawing
<ContentControl>
BoardViewModel
</ContentControl>
it will draw
<ContentControl>
<local:BoardView />
</ContentControl>
Now the BoardView could contain something like
<ItemsControl ItemsSource="{Binding Squares}">
<ItemsControl.ItemTemplate>
<ItemsPanelTemplate>
<UniformGrid Rows="3" Columns="3" />
</ItemsPanelTemplate>
<ItemsControl.ItemTemplate>
</ItemsControl>
and it would draw a board using a 3x3 UniformGrid, with each cell containing the contents of your Squares array. If your BoardViewModel.Squares property happened to be an array of TileModel objects, then each grid cell would contain a TileModel, and you could again use an implicit DataTemplate to tell WPF how to draw each TileModel
Now as for how your ViewModel gets its actual data objects, that's up to you. I prefer to abstract all data access behind a class such as a Repository, and have my ViewModel simply call something like SodokuRepository.GetSavedGame(gameId);. It makes the application easy to test and maintain.
However you get your data, keep in mind that the ViewModel and Models are your application, so they should be responsible for getting data. Don't do that in the View. Personally I like keeping my Model layer for plain objects that hold data only, so only ever perform data access operations from my ViewModels.
For communication between ViewModels, I actually have an article on my blog about that. To summarize, use a messaging system such as Microsoft Prism's EventAggregator or MVVM Light's Messenger. They work like a kind of paging system: any class can subscribe to receive messages of a specific type, and any class can broadcast messages.
For example, your ShellViewModel might subscribe to receive ExitProgram messages and close the application when it hears one, and you can broadcast an ExitProgram message from anywhere in your application.
I suppose another method would be to just attach handlers from one class to another, such as calling CurrentBoardViewModel.ExitCommand += Exit; from the ShellViewModel, but I find that messy and prefer using a messaging system.
Anyways, I hope that answers some of your questions and will point you in the right direction. Goodluck with your project :)

MVVM ViewModel to View Communication

I am new to MVVM and working on an application, i want to achieve few things in my application
My viewmodel should be able to initiate a new view.
scenario(a command is bind to a button and some process decide what to do and based on the result, i need to show View1 or View2)
Upon a successfull operation my viewmodel should display a messagebox, if multiple views are open then message must prompt upon the right view(with which viewmodel is bind).
I want to provide some kind of notification from my view model to view. Kindly guide me in the right direction.
Thanks
You might want to try out some of the many mvvm frameworks out there. I personally like mvvm light because it works in silverlight and WPF, and it's easy to use http://mvvmlight.codeplex.com/ (no affiliation)
Here is a nice compare/contrast of some of the major frameworks: What framework for MVVM should I use?
Most of the frameworks have a messaging system that provides the ability to send updates between the view and the viewmodel as well as between viewmodels. Most of the frameworks also provide canned messages that handle MVVM messageboxs as well (I know MVVM Light does).
To handle switching between views in WPF I use DataTemplates and Content controls
In the view .xaml I add
<ContentControl Content="{Binding ActiveViewModel}" />
and this is the space where the injected view will be displayed. The ActiveViewModel is the object for the viewModel that holds the selected viewModel.
In a ResourceDictionary I add something like:
<DataTemplate DataType="{x:Type ViewModelNameSpace:ViewModelClassName}">
<ViewNameSpace:ViewClasName/>
</DataTemplate>
Finally in the ViewModel I set the ActiveViewModel property (that is setup to notify the UI of changes via INotifyPropertyChanged) to an instance of the viewModel I would like to use.
ActiveViewModel = new ViewModelClass();
You should create a new View and Navigate to it.
You can use messaging in MVVM Light framework. Send message from your ViewModel to View. Examples:
http://chriskoenig.net/2010/07/05/mvvm-light-messaging/

Categories