我已经尝试了几个小时才能达到可以启动 WPF 应用程序并完全控制的程度。我希望能够创建一个 ViewModel,创建一个视图(窗口),将视图的数据上下文设置为 ViewModel,然后显示视图。
我尝试了很多方法,最有希望的是将App.xaml更改为页面,然后添加我自己的Main方法。不幸的是,这无法正常工作,因为 VS2010 不会在设计器中显示 App.xaml 中的样式,尽管它们在运行应用程序时确实有效。
有办法做我想做的事吗?如果没有,人们通常如何在 WPF 中启动 MVVM 应用程序,在 View 本身之外创建 ViewModel?
我会使用启动事件。您可以将其添加到 App.xaml 并删除 StartupUri 行。添加它后,Visual Studio 可以在 App.xaml.cs 文件中为您创建事件。您可以在其中初始化您的 ViewModel 和 View。
这是一种简单的方法...
<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>
这是基本的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
也可以使用。 第一个显示的窗口将自动分配给主窗口。 当然,您可以跳过创建 mainView
并直接写入 MainWindow
,这也会简化语法。
MainWindow = new MainView();
MainWindow.Show();
MainWindow.DataContext = new MainViewModel();
最后一点,我在数据绑定之前执行
Show
。您需要这样做以避免 MainViewModel
在创建过程中抛出异常。 如果尚未显示 MainView
,应用程序将关闭,而不会让您看到错误。
在我们的应用程序中,我们选择了您已经建议的方式:编写一个新的 Main 方法。然后,您还必须对项目应用程序设置进行一些更改(无启动对象)。应用程序 xaml 必须看起来像这样:
<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>
背后的代码看起来像这样:
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;
}
}
查看启动事件并注意,App.xaml 中未指定默认 StartupUri
您还可以在 MainWindow 的新构造函数中传递 DataContext,或者直接在 xaml 中创建 DataContext。
将 ViewModel 实例分配给视图的 DataContext 的最简单方法是在 Window 后面的代码中。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new myViewModel();
}
}
对于问题的第一部分,您可以在启动事件中拥有应用程序的control
<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>
背后代码:
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
// Place your code here
}
}
如果您将 MVVM 与 DI 结合使用(例如 CommunityToolkit),您可以使用如下内容:
/// <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;
}