2009-02-12 17 views
34

Tło: Tworzę aplikację WPF przy użyciu MVVM i przy użyciu kontenera DI zbudować moje ViewModelsPlik App.xaml nie zostanie przeanalizowany, jeśli moja aplikacja nie ustawia StartupUri?

My App.xaml wygląda następująco:

<Application x:Class="WpfApp.App" 
    ...xmlns etc... 
    StartupUri="MainWindow.xaml"> 
    <Application.Resources> 
     <app:ServiceLocator x:Key="serviceLocator" /> 
    </Application.Resources> 
</Application> 

MainWindow.xaml wygląda następująco:

<Window x:Class="CompositeMefWpfApp.MainWindow" 
    ...xmlns etc... > 
    <Control.DataContext> 
     <Binding Path="MainWindowViewModel" Source="{StaticResource serviceLocator}" /> 
    </Control.DataContext> 

Teraz wszystko działa dobrze, ale StartupUri jest zakodowane na stałe w XAML, którego nie chcę.
Po kierunkiem kilku blogposts i artykułów znalazłem, usunąłem StartupUri i próbowali stworzyć MainWindow zaczepiając OnStartup w App.xaml.cs, tak:

protected override void OnStartup(StartupEventArgs e) 
{ 
    base.OnStartup(e); 
    new MainWindow().Show(); 
} 

Problem polega na tym, awarii aplikacji podczas próby wyświetlenia okna, z tym wyjątkiem:

Nie można odnaleźć zasobu o nazwie "{serviceLocator}". W nazwach zasobów rozróżniana jest wielkość liter. Błąd na obiekcie „” w pliku System.Windows.Data.Binding znaczników „WpfApp; komponent/mainwindow.xaml” linia 8 miejsce 45.

O ile mogę powiedzieć, sekcja <Application.Resources> jest po prostu nie do odczytania z pliku xaml. Mogę umieścić jakiś kod w OnStartup dodać zasób programowo tak:

Resources.BeginInit(); 
Resources.Add("serviceLocator", new ServiceLocator()); 
Resources.EndInit(); 

Jednak to brzydki hack, i nie może mi pomóc, gdybym chciał umieścić coś innego w pliku App.xaml później ? :-(

powinienem być podpinania innego zdarzenia Czy istnieje sposób obejścia tego

Odpowiedz

38

zamiast nadrzędnymi OnStartup, spróbuj użyć zdarzenia zamiast:

<Application x:Class="My.App" 
    xmlns="..." 
    Startup="Application_Startup" 
    ShutdownMode="OnExplicitShutdown"> 
     <Application.Resources> 
      <app:ServiceLocator x:Key="serviceLocator" /> 
     </Application.Resources> 
    </Application> 

Kod za:

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(); 
    } 
} 
+1

To rozwiązuje, dzięki! –

+1

OMG, dziękuję! Myślałem, że oszaleję. – Heliac

+1

Dlaczego ważne jest skonfigurowanie zdarzenia z xaml? Nie powiedzie się, jeśli skonfigurowane z konstruktora ... –

12

Napotkali podobny/ten sam problem. Występuje błąd generowania kodu VS, w którym kod niezbędny do połączenia <Application.Resources> z resztą programu czasami nie jest wstawiany, gdy <Application.Resources> zawiera tylko jedną pozycję i nie ma atrybutu StartupUri.

Szczegóły: http://bengribaudo.com/blog/2010/08/19/106/bug-single-application-resources-entry-ignored(disclaimer - dowiązanie moim blogu)

+2

Visual Studio 2012 z .NET Framework 4.5 Nadal ma błąd – Lu55

+0

Visual Studio 2015 nadal ma błąd :-(Kolejne trzy godziny mojego życia tam nie ma –

17

Najbardziej proste obejście jest definicja x: Imię:

<Application x:Name="App" ... 
    <Application.Resources> 
     ... 
    </Application.Resources> 
</Application> 

Więcej informacji: http://connect.microsoft.com/VisualStudio/feedback/details/472729/wpf-cannot-find-resource-defined-in-the-app-xaml-file

+0

link jest uszkodzony Nie można nawet znaleźć problemu poprzez wyszukiwanie – Lu55

+0

Dodano nowe https://connect.microsoft.com/VisualStudio/feedback/details/772087/ – Lu55

+0

To rozwiązanie sprawdziło się i jest najprostsze. – bignermo

1

Aby obejść ten błąd, można również programowo dodawać zasoby.

var rd = new ResourceDictionary() 
rd.Source = new Uri("pack://application:,,,/Resources;component/Colors.xaml"); 
Resources.MergedDictionaries.Add(rd); 

Ten kod można umieścić wewnątrz tabletu dla klasy App.