Файл app.xaml не анализируется, если мое приложение не устанавливает StartupUri? - PullRequest
41 голосов
/ 13 февраля 2009

Справочная информация: я создаю приложение WPF, используя MVVM, и использую DI-контейнер для построения моих ViewModels

Мой 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; component / mainwindow.xaml» Строка 8, позиция 45.

Насколько я могу судить, раздел <Application.Resources> просто не читается из файла xaml. Я могу поместить некоторый код в OnStartup, чтобы добавить ресурс программно следующим образом:

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

Однако это уродливый хак, и он не поможет мне, если я захочу добавить что-нибудь еще в файл app.xaml позже: - (

Должен ли я подключить какое-то другое событие? Есть ли способ обойти это?

Ответы [ 4 ]

45 голосов
/ 17 февраля 2009

Вместо того, чтобы переопределять 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();
    }
}
22 голосов
/ 09 октября 2010

Самый простой обходной путь - это определение x: Имя :

<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

13 голосов
/ 19 августа 2010

Я столкнулся с подобной / этой же проблемой. Есть ошибка генерации кода VS, когда код, необходимый для подключения <Application.Resources> к остальной части программы, иногда не вставляется, когда <Application.Resources> содержит только одну запись и не имеет атрибута StartupUri.

Подробнее: http://bengribaudo.com/blog/2010/08/19/106/bug-single-application-resources-entry-ignored (отказ от ответственности - ссылка указывает на мой блог)

2 голосов
/ 23 августа 2013

Чтобы обойти эту известную ошибку, вы также можете просто добавить ресурсы программно.

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

Этот код можно разместить внутри конструктора для класса App.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...