Подтвердить что ты не робот

Файл App.xaml не обрабатывается, если мое приложение не устанавливает StartupUri?

Фон: я создаю приложение WPF с использованием MVVM и используя контейнер DI для создания моих ViewModels

My 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 позже: - (

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

4b9b3361

Ответ 1

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

Ответ 3

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

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

Ответ 4

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

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

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