App.xaml di file non viene analizzata se la mia applicazione non imposta uno StartupUri?
Domanda
Background: Sto creando un'applicazione WPF utilizzando MVVM, e l'utilizzo di un contenitore DI costruire i miei ViewModels
Il mio App.xaml si presenta così:
<Application x:Class="WpfApp.App"
...xmlns etc...
StartupUri="MainWindow.xaml">
<Application.Resources>
<app:ServiceLocator x:Key="serviceLocator" />
</Application.Resources>
</Application>
MainWindow.xaml assomiglia a questo:
<Window x:Class="CompositeMefWpfApp.MainWindow"
...xmlns etc... >
<Control.DataContext>
<Binding Path="MainWindowViewModel" Source="{StaticResource serviceLocator}" />
</Control.DataContext>
Ora, tutto questo funziona benissimo, ma il StartupUri
è insita nel XAML, che io non voglio.
Seguendo la guida di diversi blogposts e articoli che ho trovato, ho rimosso il StartupUri
, e ho cercato di creare il MainWindow
agganciando OnStartup
in App.xaml.cs, in questo modo:
protected override void OnStartup( StartupEventArgs e )
{
base.OnStartup(e);
new MainWindow().Show();
}
Il problema è che l'applicazione si blocca quando si tenta di visualizzare la finestra, con questa eccezione:
Non riesci a trovare risorse denominato '{} ServiceLocator'. i nomi delle risorse sono case sensitive. Errore in oggetto 'System.Windows.Data.Binding' nel file di markup 'WpfApp; component / MainWindow.xaml'. Linea 8 Posizione 45
Per quanto posso dire, la sezione <Application.Resources>
è semplicemente non vengono letti dal file XAML. Posso mettere un po 'di codice nel OnStartup per aggiungere la risorsa programatically in questo modo:
Resources.BeginInit();
Resources.Add("serviceLocator", new ServiceLocator());
Resources.EndInit();
Tuttavia questo è un brutto hack, e non mi aiuta se ho voluto mettere qualcosa di diverso nel file App.xaml seguito: - (
Dovrei conquistano gli qualche altro evento? C'è un modo per aggirare questo?
Soluzione
Piuttosto che sovrascrivendo OnStartup, provare a utilizzare un evento invece:
<Application x:Class="My.App"
xmlns="..."
Startup="Application_Startup"
ShutdownMode="OnExplicitShutdown">
<Application.Resources>
<app:ServiceLocator x:Key="serviceLocator" />
</Application.Resources>
</Application>
Codice dietro:
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();
}
}
Altri suggerimenti
La soluzione più semplice è la definizione di un x: Nome :
<Application x:Name="App" ...
<Application.Resources>
...
</Application.Resources>
</Application>
Più informazioni: http://connect.microsoft.com/VisualStudio/feedback/details/472729/wpf-cannot-find-resource-defined-in-the-app-xaml-file
Ho eseguito in un / questo stesso problema simile. C'è un VS generazione di codice bug in cui il codice necessario per collegare <Application.Resources>
al resto del programma a volte non è inserito quando <Application.Resources>
contiene una sola voce e non dispone di un attributo StartupUri
.
Dettagli: http://bengribaudo.com/blog / 2010/08/19/106 / bug-single-application-risorse-entry-ignorato (disclaimer - collegamento punti al mio blog)
Per ovviare a questo problema sapere che si può anche solo aggiungere risorse a livello di codice.
var rd = new ResourceDictionary()
rd.Source = new Uri("pack://application:,,,/Resources;component/Colors.xaml");
Resources.MergedDictionaries.Add(rd);
Questo codice può essere collocato all'interno del construtor per la classe App
.