web-dev-qa-db-ja.com

アプリがStartupUriを設定しない場合、App.xamlファイルは解析されませんか?

背景:MVVMを使用してWPFアプリを作成し、DIコンテナーを使用してViewModelを構築しています

私の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を削除し、App.xaml.csでMainWindowをフックしてOnStartupを作成しようとしました。 、 このような:

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

問題は、次の例外を除いて、ウィンドウを表示しようとするとアプリがクラッシュすることです。

'{serviceLocator}'という名前のリソースが見つかりません。リソース名では大文字と小文字が区別されます。マークアップファイル「WpfApp; component /mainwindow.xaml」のオブジェクト「System.Windows.Data.Binding」でエラーが発生しました。8行目位置45。

私の知る限り、<Application.Resources>セクションがxamlファイルから読み取られていないだけです。 OnStartupにコードを入れて、次のようにプログラムでリソースを追加できます。

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

ただし、これは醜いハックであり、後でapp.xamlファイルに何か他のものを入れたい場合は役に立ちません:-(

他のイベントをフックする必要がありますか?これを回避する方法はありますか?

44
Orion Edwards

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();
    }
}
46
Nidonocu

最も簡単な回避策は、x:Nameの定義です。

<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

23
jbe

私は同様の/これと同じ問題に遭遇しました。 <Application.Resources>にエントリが1つだけ含まれ、StartupUri属性がない場合、<Application.Resources>をプログラムの残りの部分に接続するために必要なコードが挿入されないことがあるVSコード生成のバグがあります。

詳細: http://bengribaudo.com/blog/2010/08/19/106/bug-single-application-resources-entry-ignored(免責事項- -リンクは私のブログを指しています)

13
Ben Gribaudo

この既知のバグを回避するには、プログラムでリソースを追加することもできます。

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

このコードは、Appクラスのコンストラクター内に配置できます。

2
user1412631