2

I got a wpf desktop application with 3 ViewModels. I have 1 ViewModel that contains a tabhost and tabs. And I got 2 tabs. Each of those tabs has it's own ViewModel.
The problem I have is that in tab1 I have a listview with searchresults and a button. When I select one item in that list and press the button, I want to change tab and display information about that item I selected in tab2.
I have searched for a solution, but it seems to include creating all ViewModels in the MainViewModel and providing a reference of the MainViewModel to all the subViewModels.
Is there no other way?



EDIT

I just managed to solve my problems with MVVM light that I added to the project.

By binding a method in the MainViewModel and a property in it to the .xaml I can now call it from tab1 with info to tell it to change tab. Also, by binding a method in tab2 I can now send over an item from tab1 in the same manner.

This is how I solved it after importing MVVM light into the project.
In tab1

Messenger.Default.Send<string, tab2ViewModel>(--object to send to tab2--);
Messenger.Default.Send<int, MainViewModel>(--tab index--);

In Main/tab2

Messenger.Default.Register<int>(this, ChangeTab);
public void ChangeTab(int i)
{
   SelectedTabIndex = i; //Bound property in .xaml
}

It seems to automagically just work..

P.s. Thanx for reply. I shall look into how Prism work as well, and see if there is any advantages to use that instead of MVVM light(Not right now however).

H.B.
  • 166,899
  • 29
  • 327
  • 400
prigas
  • 23
  • 5
  • Can you bind tab2's DataContext property to tab1's SelectedItem? – snurre Sep 21 '11 at 09:43
  • No, I dont think so atleast. Because they are in separate .xaml files as well. – prigas Sep 21 '11 at 11:34
  • I do not recommend directly using .NET types to send messages because as it is broadcasted, as other view-model might listen to this type, your application will get quickly spammed and you will have to do horrible handling. Create a type base on GenericMessage. Also I think you can accept the answer. – Ucodia Sep 21 '11 at 12:26
  • I see, I wassnt sure if that was the case as I was specifying a specific ViewModel, in this case MainViewModel etc. I did do notice that I could register 2 methods in the VM and that both where called with 1 send. It is a nice feature that I will make use of. Are you sure that specifying MainViewModel in the Send method wont limit it to that class? – prigas Sep 21 '11 at 12:57
  • The issue with not using .Net types because they are broadcast is handled in MVVM light Messaging by using tokens. – jfin3204 Mar 24 '14 at 14:26

1 Answers1

1

A good solution to your problem would be to use the EventAggregator of Prism.

This service lets you listen to and publish a particular type of event from anywhere in your application without tying your view-models to each other. This is a really nice solution for MVVM and other losely-coupled designs. It is easy and works like a charm.

You can find the documentation here : EventAggregator More information about Prism here : Prism on Codeplex


Here is a concrete sample. Imagine you want to change the title of the main Window from anywhere in the application. You would create this event:

public class TitleChangedEvent : CompositePresentationEvent<string>{}

Then you would suscribe to this event in your MainWindowViewModel like this:

eventAggregator.GetEvent<TitleChangedEvent.Suscribe(
(newTitle) =>
{
    this.WindowTitle = newTitle;
});

And finally you can update the title from anywhere in your application like this:

eventAggregator.GetEvent<TitleChangedEvent>().Publish("This is a new title!");

Quite easy as you can see.


Smililarly with MVVM Light you would first create a message for notification:

public class TitleChangedMessage : GenericMessage<string>{}

Then you would listen to the message like this in your MainWindowViewModel:

Messenger.Register<TitleChangedMessage>(this, 
(message) =>
{
    this.WindowTitle = message.Content;
}

And you would send an update like this:

Messenger.Send<TitleChangedMessage>(this, new TitleChangedMessage("This is a new title!"));

This is the MVVM Light way to do it :)

You can also have a look at this related question: Messenger class in MVVM Light

Community
  • 1
  • 1
Ucodia
  • 7,410
  • 11
  • 47
  • 81
  • That looks kinda neat. While I wrote the first post I had just started to look into MVVM light. And from the little I have learned I think it works almost in the same manner as Prism. Do you happen to know the difference? Is it better to use Prism instead of MVVM light perhaps? Really odd how simular they look based on the code Ive seen... – prigas Sep 21 '11 at 11:46
  • I updated my answer. About the choice of framework they are different. MVVM Light is more oriented on the MVVM pattern while Prism is more oriented on application modularity. But in the end, what they do is pretty much the same. I personnaly prefer Prism as it has built-in support for MEF (modularity framework provided with .NET 4.0). – Ucodia Sep 21 '11 at 12:23
  • Thanx for the update. I think I will stay with MVVM light then as they seem to be so simular and Ive implemented it already. And because it is more oriented on the MVVM pattern according to you :) – prigas Sep 21 '11 at 12:52