App.xaml archivo no consigue analiza si mi aplicación no establece un StartupUri?
Pregunta
Antecedentes: Estoy creando una aplicación de WPF usando MVVM, y el uso de un contenedor DI para construir mis ViewModels
Mi App.xaml se ve así:
<Application x:Class="WpfApp.App"
...xmlns etc...
StartupUri="MainWindow.xaml">
<Application.Resources>
<app:ServiceLocator x:Key="serviceLocator" />
</Application.Resources>
</Application>
MainWindow.xaml se parece a esto:
<Window x:Class="CompositeMefWpfApp.MainWindow"
...xmlns etc... >
<Control.DataContext>
<Binding Path="MainWindowViewModel" Source="{StaticResource serviceLocator}" />
</Control.DataContext>
Ahora, todo esto funciona bien, pero el StartupUri
está codificada en el XAML, que no quiero.
Siguiendo la orientación de varias entradas del blog y artículos que he encontrado, me quita el StartupUri
, y trató de crear el MainWindow
enganchando OnStartup
en App.xaml.cs, como esto:
protected override void OnStartup( StartupEventArgs e )
{
base.OnStartup(e);
new MainWindow().Show();
}
El problema es, la aplicación se bloquea al intentar mostrar la ventana, con esta excepción:
No se puede encontrar el recurso llamado '{} ServiceLocator'. nombres de recursos entre mayúsculas y minúsculas. Error en el objeto 'System.Windows.Data.Binding' en el archivo de anotación 'WpfApp; componente / MainWindow.xaml'. La línea 8 Posición 45
Por lo que yo puedo decir, la sección <Application.Resources>
simplemente no está siendo leído fuera del archivo XAML. Puedo poner un poco de código en el OnStartup añadir el recurso programáticamente como esto:
Resources.BeginInit();
Resources.Add("serviceLocator", new ServiceLocator());
Resources.EndInit();
Sin embargo eso es un truco feo, y no me ayuda si quería poner algo más en el archivo App.xaml más adelante: - (
¿Debo estar enganchando algún otro evento? ¿Hay una manera de evitar esto?
Solución
En lugar de anular OnStartup, intente utilizar un evento en su lugar:
<Application x:Class="My.App"
xmlns="..."
Startup="Application_Startup"
ShutdownMode="OnExplicitShutdown">
<Application.Resources>
<app:ServiceLocator x:Key="serviceLocator" />
</Application.Resources>
</Application>
Código atrás:
public partial class App : Application
{
public App()
{ }
private void Application_Startup(object sender, StartupEventArgs e)
{
// TODO: Parse commandline arguments and other startup work
new MainWindow().Show();
}
}
Otros consejos
El más sencilla solución es la definición de un x: Nombre
<Application x:Name="App" ...
<Application.Resources>
...
</Application.Resources>
</Application>
Más información: http://connect.microsoft.com/VisualStudio/feedback/details/472729/wpf-cannot-find-resource-defined-in-the-app-xaml-file
Me he encontrado con un problema similar este mismo /. Hay un insecto generación de código VS en el que el código necesario para conectar <Application.Resources>
al resto del programa veces no se inserta cuando <Application.Resources>
contiene una sola entrada y no tiene un atributo StartupUri
.
detalles: http://bengribaudo.com/blog / 2010/08/19/106 / fallo de un solo-Application-recursos-entrada-ignorado (disclaimer - enlace apunta a mi blog)
Para evitar este error conocimientos también se puede simplemente añadir recursos mediante programación.
var rd = new ResourceDictionary()
rd.Source = new Uri("pack://application:,,,/Resources;component/Colors.xaml");
Resources.MergedDictionaries.Add(rd);
Este código se puede colocar dentro de la construtor para la clase App
.