Unfortunately, I was unable to reproduce your specific issue. I fired off a separate thread in my MainWindowView Loaded event handler; a thread which did nothing but continuously send a specific message. I then called ShowDialog() on my SecondWindowView, whose view model was registered to listen to this specific message. The message handler in the second window's view model executed repeatedly. In fact, the handler was being called even before ShowDailog() was called since my view model was already created by the ViewModelLocator at application startup. I would need to see some more code to get a better idea of what's going on in your case (i.e. your service that is creating the details window, or something that I can compile to reproduce the issue).
You might try the following approach, instead, for your child window. Define the following classes somewhere in your application:
public class ShowChildWindowMessage : MessageBase { }
public class HideChildWindowMessage : MessageBase { }
public class DisplayDetailsMessage : MessageBase { }
Now create the following ChildWindowVM class and initialize it in your ViewModelLocator the same way the MainWindowVM is initialized:
public class ChildWindowVM : ViewModelBase
{
private ViewModelBase m_currentContent;
public ViewModelBase CurrentContent
{
get { return m_currentContent; }
set
{
NotifySetProperty(ref m_currentContent, value, () => CurrentContent);
if (m_currentContent != null)
{
m_currentContent.Refresh();
Messenger.Default.Send(new ShowChildWindowMessage());
}
}
}
public ChildWindowVM()
{
Messenger.Default.Register<DisplayDetailsMessage>(this, OnDisplayDetails);
}
private void OnDisplayDetails(DisplayDetailsMessage msg)
{
CurrentContent = ViewModelLocator.DetailsViewModel; // or whatever view model you want to display
}
}
The Refresh() method would be defined in the DetailsViewModel class and would take care of any initialization you would like to perform before displaying the window. Note that when the CurrentContent property is set then a message is fired off to the MainWindowView to create a ChildWindowView instance in which to display your content.
The MainWindowView code looks like this:
public partial class MainWindowView : Window
{
private ChildWindowView m_childWindowView;
public MainWindowView()
{
InitializeComponent();
Closing += () => ViewModelLocator.CleanUp();
Messenger.Default.Register<ShowChildWindowMessage>(this, OnShowChildWindow);
Messenger.Default.Register<HideChildWindowMessage>(this, OnHideChildWindow);
}
private void OnShowChildWindow(ShowChildWindowMessage msg)
{
m_childWindowView = new ChildWindowView();
m_childWindowView.ShowDialog();
}
private void OnHideChildWindow(HideChildWindowMessage msg)
{
m_childWindowView.Close();
}
}
The last step is to bind the CurrentContent property from the ChildWindowVM class to your ChildWindowView class. This is done in the xaml for your ChildWindowView:
<Window x:Class="Garmin.Cartography.AdminBucketTools.ChildWindowView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding Path=ChildWindowVm, Source={StaticResource Locator}}">
<Grid>
<ContentPresenter Content="{Binding Path=CurrentContent}" />
</Grid>
Now you can display your details from anywhere in your application simply by calling
Messenger.Default.Send(new DisplayDetailsMessage());
And you can close the window programmatically by calling
Messenger.Default.Send(new HideChildWindowMessage());
You can also derive as many classes as you want from MessageBase and register for them in your ChildWindowVM class. In each message handler, you can then specify which content to show simply by setting the CurrentContent property to the appropriate view model.
One more thing, actually. You'll need to specify the template binding between your views and view models if you actually want to see anything useful in your child window. This can be done via xaml in your application resources:
<DataTemplate DataType="{x:Type viewmodels:DetailsViewModel}">
<views:DetailsView />
</DataTemplate>
Don't forget to define the namespaces (i.e. "viewmodels" and "views").