Toggle two views (Windows) in MVVM WPF
I am developing an application w开发者_开发技巧hich has 2 Modes
- Configuration Mode
- Execution Mode
Boths modes will open in new window. I have already made the configuration Window.
I need to switch between 2 Modes by pressing Key F12
or something like that.... also i have to prompt the user for password while switching from Execution to configutation mode (Just once durnig the session) i have made the password screen and implemented in configuration.
I am also worried as i have used Messenger(Meaditor pattern) so closing and opening of 2 different windows will register the delegates again nad again... and i am launching Modal windows
.
Also do we need to keep both the Views alive or i can kill one of them on toggling.
Totally confused about the implementation...
My App.Xaml Code
/// <summary>
/// Application_Startup
/// </summary>
/// <param name = "sender"></param>
/// <param name = "e"></param>
private void Application_Startup(object sender, StartupEventArgs e)
{
log.Debug("Application_Startup " + Utility.FUNCTION_ENTERED_LOG);
try
{
if (e.Args.Length == 0)
{
AboutDialog.SpashScreen(Utility.TOOL_NAME,
Utility.TOOL_VERSION);
MainView mainForm = new MainView();
mainForm.ShowDialog();
}
else
{
string key = null;
foreach (string arg in e.Args)
{
if (arg.StartsWith("-"))
{
//this is a key
key = arg;
if (key.Equals("-config"))
{
CommandLineArgs.Add(key, "config");
break;
}
if (key.Equals("-start"))
{
CommandLineArgs.Add(key, "start");
}
}
else
{
//should be a value
if (key == null)
{
throw new Exception(
"The command line arguments are malformed.");
}
CommandLineArgs.Add(key, arg);
key = null;
}
}
string config = string.Empty;
foreach (object k in App.CommandLineArgs.Keys)
{
config += CommandLineArgs[k].ToString();
}
switch (config)
{
case "config":
AboutDialog.SpashScreen(
Utility.TOOL_NAME,
Utility.TOOL_VERSION);
MainView mainForm = new MainView();
mainForm.ShowDialog();
break;
case "start" :
ExecutionForm execuForm= new ExecutionForm();
execuForm.ShowDialog();
break;
default:
MessageBox.Show("Incorrect Parameters",
Utility.TOOL_NAME);
Application.Current.Shutdown();
break;
}
}
log.Debug("Application_Startup" + Utility.FUNCTION_EXIT_LOG);
}
catch (Exception ex)
{
log.Error("Application_Startup" + ex.Message, ex);
}
}
Your implementation doesnt look totally wrong to me.
If I am given a requirement to swtich between two views on a modal window by a key press then I would have gone the MVVM way...
- Use single modal window that hosts multiple contents situationally.
Have a
ContentControl
on the Window. Bind theContent
to theDataContext
.<DockPanel LastChildFill="true"> <Menu DockPanel.Dock="Top" ...> </Menu> <ContentControl Content="{Binding}" ... /> </DockPanel>
Create two data templates as resources. One data template corresponds to the view of "Config" and other data template is for 'Execution" view.
<Window.Resources> <DataTemplate x:Key="ConfigView" ... /> <DataTemplate x:Key="ExecutionView" ... /> </Window.Resources>
You can keep these data templates in different resources files and merge the resource dictionaries to the window resources.
Create a single ViewModel with a writeable
Mode
property. Have INotifyPropertyChanged implemented.public class ViewModel : INotifPropertyChanged { private string mode; public string Mode { get { return mode; } set { mode = value; NotifPropertyChanged("Mode"); } } private IComamnd changeModeCommand; public ICommand ChangeModeCommand { get { if (changeModeCommand == null) changeModeCommand = new DelegateCommand( OnModeChange, CanModeChange); return changeModeCommand; } } //// Other properties and functions go here ... }
In the code above DelegateCommand
is not internally found in .Net APIs. Get their implementation from the internet.
Register a
KeyBinding
forF12
on the window. TheCommand
for F12KeyBinding
comes from theViewModel
.<Window.InputBindings> <KeyBinding Command="{Binding ChangeModeCommand}" Key="F12" /> </Window.InputBindings>
In versions prior to .Net 4.0, the Command
property is not bindable. use CommandReference for this.
OnModeChange() for
F12
key, switch theMode
fromViewModel
class and raise property changed Notification.Have data triggers on the
ContentControl
on theWindow
. In the data triggers checkMode
if it is "Config" and change theContentTemplate
to "Config" data template othwerise change to "Execution" datatemplate.<ContentControl Content="{Binding}"> <ContentControl.Style> <Style TargetType="{x:Type ContentControl}"> <Style.Triggers> <DataTrigger Binding="{Binding Mode}" Value="Config"> <Setter Property="ContentTemplate" Value="{StaticResource ConfigView}"/> </DataTrigger> <DataTrigger Binding="{Binding Mode}" Value="Execution"> <Setter Property="ContentTemplate" Value="{StaticResource ExecutionView}"/> </DataTrigger> </Style.Triggers> </Style> </ContentControl.Style> </ContentControl>
I hope my way helps you in some sense.
精彩评论