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

StackOverflow https://stackoverflow.com/questions/543414

  •  23-08-2019
  •  | 
  •  

Вопрос

Фон:Я создаю приложение 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 сорт.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top