4

WP8プロジェクトを自作のMVVM実装からMVVMLightに調整しようとしています。私はこの例をうまくやり遂げました、そしてそれは完璧に働きました。その後、自分のプロジェクトで同じ手順を繰り返し始めました。

アプリケーションはエラーなしでコンパイルされますが、Expression BlendでMainPage.xamlを開くと、次のエラーが発生します。

クラスproject.Services.IDataServiceはすでに登録されています。App.xaml、6行目、5列目

調べてみると、ViewModelLocatorが登録されている行です。

<Application.Resources>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
</Application.Resources>

私のViewModelLocator.cs:

        /// <summary>
        /// Initializes a new instance of the ViewModelLocator class.
        /// </summary>
        public ViewModelLocator()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

            if (ViewModelBase.IsInDesignModeStatic)
            {
                // Create design time view services and models
                // see: http://developingux.com/2012/06/10/how-to-fix-error-design-time-data-in-blend-with-mvvm-light/
                if (!SimpleIoc.Default.IsRegistered<IDataService>())
                {
                    SimpleIoc.Default.Register<IDataService, DesignDataService>();
                }
            }
            else
            {
                // Create run time view services and models
                if (!SimpleIoc.Default.IsRegistered<IDataService>())
                {
                    SimpleIoc.Default.Register<IDataService, DataService>();
                }
            }

            // only one ViewModel for the MainPage
            SimpleIoc.Default.Register<MainViewModel>();
        }

コードコメントからわかるように、ここで想定されている修正をすでに試しましたが、Blendでこのエラーが発生します。IDataServiceを登録できる場所が他に残っていないので、何が問題になる可能性がありますか?SOに関するその他の質問は、特にデスクトップアプリケーションに関するものであり、ViewModelLocatorが登録される前に最初にチェックが行われる上記の修正の一部のみが含まれています。

何か案は?:)

更新1: VisualStudioでデザイン時間を表示することができました。コードビハインドファイルでDataContextを手動で参照していました。ただし、Blendで設計時データを表示できないという問題を解決する必要があります。Visual Studioの動作から判断すると、動作するはずです。

4

3 に答える 3

5

古い質問ですが、それでも関連性があり、原因はまだ説明されておらず、直接的な答えもありません。

設計時に、VisualStudioはリソースを複数回インスタンス化するのが好きなようです。
これにより、おそらくApp.xamlまたはその他のリソースで定義されているビューモデルロケーターが、同じ静的アプリケーションインスタンスで複数回構築されます。

これらのSimpleIoc.Default2つのビューモデルロケーターインスタンス全体に単一のインスタンスとして存在するため、新しい登録は重複した登録になります。

Visual Studioの再起動、プロジェクトの再読み込み、または強制終了XDesProc.exe(Visual StudioでのXAMLデザイナーのホストプロセス)の後で最初は機能するように見えるかもしれませんが、ウィンドウデザイナーを閉じて再度開くと、デザインタイムが得られますそのウィンドウにリンクされているリソースを再作成しようとしているため、エラーが発生します。

ビューモデルロケーターで静的ブール値を作成するなど、最初の呼び出しでtrueに設定し、それ以前にtrueに設定した場合は、戻って何も登録しないなど、いくつかの解決策を試しました。

しかし、残念ながら、ブール値がビューモデルロケーターとともに再インスタンス化されたため、これは役に立たないようです。
ビューを開くたびに再構築されない別のクラスに配置しようとすることもできますが、これは少しばかげているように見えました。

最後に、以前に登録したすべてのサービス、インスタンス、およびファクトリを削除するために、この.Reset()メソッドを使用することにしました。SimpleIoc

public ViewModelLocator()
{
    SimpleIoc.Default.Reset();

    ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

    SimpleIoc.Default.Register<IExampleService, ExampleServiceImplementation>();
    // Register the rest of your services
}

これは問題を解決するようであり、ビューモデルロケーターは一度だけインスタンス化されるため、実行時には効果がないはずです。

于 2017-03-31T21:45:17.103 に答える
4

同じ問題が発生しました。これは、XAML-Designer、静的ファクトリ/ロケータ、およびオブジェクトの設計時作成と組み合わせたVisualStudioの問題のようです。ただし、解決策は次のとおりです。

  1. 工場なしで登録する(非推奨)

    SimpleIoc.Default.Register<INavigationService>();

  2. または、ファクトリを使用する場合は、ファクトリを登録する前に登録を解除してください

    SimpleIoc.Default.Unregister<INavigationService>(); SimpleIoc.Default.Register<INavigationService>(() => new NavigationService());

  3. コンストラクターを静的にすることにより、デザイナー/ブレンドによってViewModelLocatorが複数回作成されるのを防ぎます

    static ViewModelLocator() { ... }

エラーは厄介ですが、このシナリオで発生する可能性があります。設計時に(ViewModelLocatorおそらくApp.xaml内で)オブジェクトを作成し、コードで何かを変更すると、コンパイラがトリガーされ、ViewModelLocatorが登録解除されることなく再作成されます。サービス。したがって、工場ですでに登録されていると文句を言うでしょう。理論的には、ファクトリのないクラスを複数回登録すると、エラーも発生するはずです。

于 2015-03-07T14:14:06.273 に答える
-2

ViewModelLocator.csからのコメントを何度も読んだ後、MainPage.xamlのDataContextが正しく設定されていないことがわかりました。

DataContext="{Binding Source={StaticResource Locator}, Path=Main}"

それ以外の

DataContext="{Binding Main, Source={StaticResource Locator}}"

Blendのエラーが停止し、BlendとVSで同じ設計時データを確認できるようになりました。しかし、どのようにしてこのエラーを監視しましたか?さて、ここに説明があります:

私はこのチュートリアルに専念しました。これは非常に役に立ちました。しかし、私の経験では、MVVM Lightのある種の古いバージョンであり、現在使用しているバージョンで何かが変更されている必要があります。ジェシーはパスなしでバインディングを使用しました。ただし、これは彼の例では機能しています。しかし、ここで私の特別なケースでは、ロケーターがMainViewModel(ここではMain)の正しいプロパティを識別できるようにパスを指定する必要がありました。

于 2013-01-04T08:47:35.827 に答える