Файл App.xaml не анализируется, если мое приложение не устанавливает StartupUri?
Вопрос
Фон:Я создаю приложение WPF, используя MVVM, и использую контейнер DI для создания своих моделей представления.
Мой App.xaml выглядит так:
<Application x:Class="WpfApp.App"
...xmlns etc...
StartupUri="MainWindow.xaml">
<Application.Resources>
<app:ServiceLocator x:Key="serviceLocator" />
</Application.Resources>
</Application>
MainWindow.xaml выглядит следующим образом:
<Window x:Class="CompositeMefWpfApp.MainWindow"
...xmlns etc... >
<Control.DataContext>
<Binding Path="MainWindowViewModel" Source="{StaticResource serviceLocator}" />
</Control.DataContext>
Теперь все работает нормально, но StartupUri
жестко запрограммировано в XAML, чего я не хочу.
Следуя рекомендациям нескольких найденных мной сообщений в блогах и статей, я удалил StartupUri
, и попытался создать MainWindow
зацепив OnStartup
в App.xaml.cs, вот так:
protected override void OnStartup( StartupEventArgs e )
{
base.OnStartup(e);
new MainWindow().Show();
}
Проблема в том, что приложение вылетает при попытке показать окно, за этим исключением:
Невозможно найти ресурс с именем «{serviceLocator}».Имена ресурсов чувствительны к регистру.Ошибка объекта «System.Windows.Data.Binding» в файле разметки «WpfApp;компонент/mainwindow.xaml», строка 8, позиция 45.
Насколько я могу судить, <Application.Resources>
раздел просто не считывается из файла xaml.Я могу поместить некоторый код в OnStartup, чтобы программно добавить ресурс следующим образом:
Resources.BeginInit();
Resources.Add("serviceLocator", new ServiceLocator());
Resources.EndInit();
Однако это уродливый хак, и он не поможет мне, если я захочу позже добавить что-то еще в файл app.xaml :-(
Должен ли я подключить какое-то другое событие?Есть ли способ обойти это?
Решение
Вместо переопределения OnStartup попробуйте вместо этого использовать событие:
<Application x:Class="My.App"
xmlns="..."
Startup="Application_Startup"
ShutdownMode="OnExplicitShutdown">
<Application.Resources>
<app:ServiceLocator x:Key="serviceLocator" />
</Application.Resources>
</Application>
Код позади:
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();
}
}
Другие советы
Самым простым решением является определение х: Имя:
<Application x:Name="App" ...
<Application.Resources>
...
</Application.Resources>
</Application>
Больше информации: http://connect.microsoft.com/VisualStudio/feedback/details/472729/wpf-cannot-find-resource-defined-in-the-app-xaml-file
Я столкнулся с похожей/такой же проблемой.Существует ошибка генерации кода VS, из-за которой код, необходимый для подключения, <Application.Resources>
к остальной части программы иногда не вставляется, когда <Application.Resources>
содержит только одну запись и не имеет StartupUri
атрибут.
Подробности:http://bengribaudo.com/blog/2010/08/19/106/bug-single-application-resources-entry-ignored (отказ от ответственности — ссылка указывает на мой блог)
Чтобы обойти эту ошибку, вы также можете просто добавлять ресурсы программным способом.
var rd = new ResourceDictionary()
rd.Source = new Uri("pack://application:,,,/Resources;component/Colors.xaml");
Resources.MergedDictionaries.Add(rd);
Этот код можно поместить внутри конструктора App
сорт.