Reputation: 503
I've been trying for hours to get to the point where I can start a WPF application and have full control. I want to be able to create a ViewModel, create a View (Window), set the data context of the View to be the ViewModel, then show the View.
I've tried lots of methods, the most promising being to change the App.xaml to be a page and then adding my own Main method. Unfortunately this doesn't work properly because VS2010 then does not show the styles from the App.xaml in the designer, though they do work when running the app.
Is there a way to do what I want? If not, how do people normally start MVVM apps in WPF, creating a ViewModel outside of the View itself?
Upvotes: 26
Views: 29685
Reputation: 348
If you are using MVVM with DI (for example, CommunityToolkit) you can use something like this:
/// <summary>Raises the <see cref="E:System.Windows.Application.Startup" /> event.</summary>
/// <param name="e">A <see cref="T:System.Windows.StartupEventArgs" /> that contains the event data.</param>
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var shell = Services.GetService<ShellWindow>();
var shellViewModel = Services.GetService<ShellWindowViewModel>();
shell!.Show(); // or you can check for null
shell.DataContext = shellViewModel;
}
Upvotes: 0
Reputation: 394
Here is one simple way...
<Application
x:Class="Demo.Ux.WpfApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Application>
Here is the basic App.xaml.cs
public partial class App
{
protected override void OnStartup(StartupEventArgs e)
{
try
{
var mainView = new MainView();
mainView.Show();
mainView.DataContext = new MainViewModel();
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
}
Application.MainWindow
can be used as well. The first displayed Window will be assigned to MainWindow auto-magically. Of course, you can skip creating your mainView
and write directly to MainWindow
which would thin out the syntax as well.
MainWindow = new MainView();
MainWindow.Show();
MainWindow.DataContext = new MainViewModel();
One final note, I'm doing the Show
before the data bind. You need to do this to avoid a situation where the MainViewModel
throw an exception during creation. If the MainView
hasn't been shown, the app will close without letting you see the error.
Upvotes: 25
Reputation: 1849
in our application, we have choosen the way which you already proposed: writing a new Main method. You also have to make some changes in the project application settings then (no startup object). The app xaml has to look something like this:
<Application x:Class="EVOCURA.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup"
Exit="Application_Exit">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!--Custom Controls-->
<ResourceDictionary Source="<your resources here>"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
The code behind will look something like this:
public sealed partial class App : Application
{
static App()
{ }
public App()
{ }
private void Application_Startup(object sender, StartupEventArgs e)
{
// create the main window and assign your datacontext
MainAppWindow main = new MainAppWindow();
main.DataContext = <your datacontext here>
main.Show();
}
[STAThreadAttribute]
public static int Main(string[] args)
{
App app = new App();
app.InitializeComponent();
app.Run();
return 0;
}
}
Have a look at the Startup Event and notice, that no default StartupUri is specified im App.xaml
You could also pass the DataContext in a new constructor of your MainWindow, or create the DataContext directly in xaml.
Upvotes: 2
Reputation: 4971
I would use the Startup event. You can add this to the App.xaml and remove the StartupUri line. When you add it, Visual Studio can create the event for you within the App.xaml.cs file. You can initialise your ViewModel and View within.
Upvotes: 27
Reputation: 1716
The simplest way to assign an instance of the ViewModel to the DataContext of the view is in the code behind of the Window.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new myViewModel();
}
}
For the first part of your question, you can have the control of your application in the StartUp event
<Application x:Class="myApplication.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml" Startup="Application_Startup">
<Application.Resources>
</Application.Resources>
</Application>
Code Behind :
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
// Place your code here
}
}
Upvotes: 1