Monday, 19 August 2013

Show a window on load in MVVM-Light

Show a window on load in MVVM-Light

I'm currently developing an application in WPF using MVVM Light Toolkit. I
have a couple windows as shells that load user controls based on a
selection at startup. These windows are MainWindow and Settings.
MainWindow, as it normally would, loads on startup. Before this windows is
shown, I'd like to show the settings window so that a configuration may be
loaded and certain settings may be entered. Now, this is relatively easy,
usually I'd just instantiate it and call ShowDialog(), but there's a few
caveats I've encountered along the way:
If I try to load Settings in the MainViewModel constructor I run into
issues with infinite recursion
I can't load Settings from MainWindow because there's several other
actions that need to take place that can't be contained in MainWindow's
code-behind. For reference, here's the relay command I have everything in
(I'll get to my reasoning behind a relay command in a second):
public bool ShowSettings()
{
Messenger.Default.Register<XDocument>(this, (xdoc) => {
CopySettings(xdoc); });
Settings settings = new Settings();
settings.ShowDialog();
LoadMainControl();
return true;
}
I can't, don't want to, load the window via (for example) a RelayCommand
and a button placed somewhere on the MainWindow form as I'd like Settings
to show before MainWindow.
I can't make Settings the main window (I.E. switch the XAML and UI Logic
out for MainWindow and Settings) as Settings needs to be reusable as
Window in case further options need to be set.
Taking all this into account, the only proper way I've found to load the
window is via binding the Loaded event in the MainWindow XAML like so:
<Window Loaded="{Binding OnWindowLoad}">
And in the MainViewModel:
The RelayCommand:
public RelayCommand OnWindowLoad
{
get;
private set;
}
Then:
OnWindowLoad = new RelayCommand(() => ShowSettings());
Then:
public bool ShowSettings()
{
Messenger.Default.Register<XDocument>(this, (xdoc) => {
CopySettings(xdoc); });
Settings settings = new Settings();
settings.ShowDialog();
LoadMainControl();
return true;
}
But, of course, Loaded can't be bound to a RelayCommand so I have to do
something like this:
<Window>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding OnWindowLoad}"
CommandParameter="{Binding OnWindowLoadParam}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Window>
Which solves the bulk of my prolems, but fails to hid MainWindow when
Settings is loaded. Are there any other ways I can load Settings without
encountering this and the other multitude of problems I've had? I've been
searching for a more efficient way, and as of yet I've not found one.

No comments:

Post a Comment