7

まず最初に、いくつかのコンテキスト。問題に精通している場合は、そのBindingExpression部分までスキップしてください。これは WPF での最初の主要なプロジェクトであるため、MVVM パターンにはまだ慣れていません。これは、私が見つけた唯一の他の同様の質問です。その精彩を欠いた答えは、私をあまり興奮させません。

私は .NET 3.5 WPF アプリケーションを作成していますが、MVVM を使用しています (自分で実装し、フレームワークはありません)。この中に、 と の数がViewsありViewModelsます。ApplicationViewこれらは、それぞれマスター内に常駐しますApplicationViewModel

ApplicationViewビューを変更する方法は、次のように で XAML DataTemplate 要素を使用することです。

<DataTemplate DataType="{x:Type viewmodels:InitViewModel}">
    <views:InitView />
</DataTemplate>

そして、本体には、プロパティにバインドする ContentControl がありますApplicationViewModel

<ContentControl Content="{Binding CurrentPageViewModel}"/>

アプリケーションを実行すると、これらすべてが正常に動作しているように見え、意図したとおりに動作します。ただし、実行後にデバッグ出力を見ると、多くのBindingExpressionエラーが発生します。

これが一例です。にプロパティ がありSplashTextますInitViewModel。これは、スプラッシュ画面 ( ) のテキストブロックにバインドされていますInitView。スプラッシュ スクリーンが終了し、ビューモデルを切り替えると、次のようになります。

System.Windows.Data Error: 39 : BindingExpression path error: 'SplashText' property not found on 'object' ''MainMenuViewModel' (HashCode=680171)'. BindingExpression:Path=SplashText; DataItem='MainMenuViewModel' (HashCode=680171); target element is 'TextBox' (Name='FeedBackBox'); target property is 'Text' (type 'String')

これはバインディングがまだ存在するためだと理解していますが、DataContext の CurrentPageViewModel プロパティが変更されています。だから私が知りたいのは:

  • これは一時的な問題ですか、つまり、ビューが使用されていないときに破棄されますか、それともビュー (および悪いバインディング) が無期限にメモリに残りますか?
  • ビューが非アクティブなときにこれらのバインディングをクリーンアップまたは非アクティブ化する方法はありますか?
  • これらをそのままにしておくと、アプリケーションのパフォーマンスにどのような影響がありますか?
  • この問題を回避するビューを切り替えるより良い方法はありますか?

前もって感謝し、モノリシックな質問をお詫びします。

編集 03/09/13 - ContentControl が datacontext を処理するため、サブビュー datacontext を設定するのは無意味であることを指摘してくれた Jehof、Francesco De Lisi、および Faster Solutions に感謝します{Binding DataContext.CurrentPageViewModel, RelativeSource={RelativeSource AncestorType={x:Type Window}}}

4

4 に答える 4

1

あなたのプロパティがエラーを生成する別のものに属している間に、あなたDataContextが行くように見えます。MainMenuViewModelViewModel

CurrentPageViewModelスプラッシュ スクリーンの前後の値は、Bindingビューの切り替え中に失われます。

問題の原因はDataContext="{Binding DataContext.CurrentPageViewModel, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"

実際、CurrentPageViewModel = InitViewModelアプリケーションが起動すると、問題はすべてViewが同じであることですDataContext(つまりInitViewModel、最初は)が、ViewModelsビューバインディングを満たすために必要なプロパティのプール全体がないと確信しています。理解するための例:

ViewXにバインドされPropertyX、 で管理されViewModelXます。 ViewYにバインドされPropertyY、 で管理されViewModelYます。両方がありDataContext = CurrentViewModelます。

起動時CurrentViewModel = ViewModelXと ViewX と ViewY の両方にDataContext = ViewModelXがあります。しかし、これは間違っています。そして、おそらくエラーが発生します。

私が通常行うことは、対応するビュー モデルを使用して DataContext (必要に応じて cs または XAML) をビュー クラスに設定し、それが適合することを確認することです。次に、必要に応じて、更新メソッドを呼び出して、ページを切り替えるたびに値を更新します。プロパティを共有している場合は、モデルを使用して情報 (および値) を一元化することを検討してください。

http://wildermuth.com/images/mvvm_layout.pngのサンプル画像

ここに画像の説明を入力

明らかに、ビューは MainWindow によってラップされたコントロールです。

それが明確であることを願っています。

于 2013-09-03T10:02:38.933 に答える
0

あなたの質問に順番に答えましょう:

  1. あなたはおそらくこれに対する答えをすでに知っています。.Net ガベージ コレクションが発生すると、View オブジェクトがヒープから削除されます。ただし、この時点までは、View オブジェクトはページのメインの DataContext にバインドされたままであり、DataContext の変更イベントに反応します。
  2. 当然行うべきことは、Views DataContext を null に設定することです。DataContext は依存関係プロパティであるため、null 値のスコープは単なるビューになります。
  3. 他の/つまらない答えが言ったように、少し遅くなりますが、それほど遅くはありません。これについてはあまり心配する必要はありません。
  4. はい。ビュー ナビゲーション オプションに関する有用なスレッドを次に示します:ビュー ナビゲーション オプション

また、フレームワークを検討することをお勧めします。MVVM Light のような軽量のものは、統合をほとんど行わずに多くの問題を解決します。これは ViewModelLocator パターンでもありますが、副作用がなく、クリーンアップ オプションが多数用意されています。

于 2013-09-03T10:05:02.880 に答える