2016-07-19 10 views
1

現在のViewModelに応じて2つのDataTemplateが切り替わります。しかし、ViewModelを切り替えるたびに、それぞれのViewのコンストラクタを呼び出して、コンストラクタ内でInitializeComponent()を呼び出すように見えます。つまり、は、DataTemplateを切り替えるたびに、それぞれのDataTemplateにバインドされた新しいビューを生成します。なぜこれが起こっているのかわかりませんが、ViewModelsを切り替えるときに新しいViewの作成を防ぐ方法がありますか?MVVM - datatemplateは新しいビューを作成します

以下は、私のMainViewにあるDataTemplatesです。

<Window.Resources> 
    <DataTemplate DataType="{x:Type viewModels:FirstPanelViewModel}"> 
     <views:FirstPanelView /> 
    </DataTemplate> 
    <DataTemplate DataType="{x:Type viewModels:SecondPanelViewModel}"> 
     <views:SecondPanelView /> 
    </DataTemplate> 
</Window.Resources> 

テンプレートがContentControlに表示されています。

<ContentControl Grid.Row="1" Content="{Binding CurrentViewModel}" />  

これは私のFirstPanelViewと同じ、私のSecondPanelViewです。とてもシンプルです。

public partial class FirstPanelView 
{ 
    public FirstPanelView() 
    { 
     InitializeComponent(); 
    } 
} 
public partial class SecondPanelView 
{ 
    public SecondPanelView() 
    { 
     InitializeComponent(); 
    } 
} 

私Iocのは、私は、カスタムマークアップ拡張機能によって、各ビューに囲まれているSecondPanelView

container.Register<IFirstPanelViewModel, FirstPanelViewModel>(new PerContainerLifetime()) 
container.Register<ISecondPanelViewModel, SecondPanelViewModel>(new PerContainerLifetime()); 

のDataContextのインスタンスを1つだけ生成することを確認します。

DataContext="{Binding Source={common:Locate}, Path=FirstPanelViewModel}" 
DataContext="{Binding Source={common:Locate}, Path=SecondPanelViewModel}" 

これは、それぞれのViewModelのGetInstanceを呼び出すだけです。

public IFirstViewModel FirstViewModel 
{ 
    get { return _container.GetInstance<IFirstPanelViewModel>(); } 
} 
public ISecondViewModel SecondViewModel 
{ 
    get { return _container.GetInstance<ISecondPanelViewModel>(); } 
} 
+3

これはWPFでの仕様です。ビューが有効範囲外になると、ビューは破棄され、再度表示する必要がある場合は再作成する必要があります。これは、ViewModelの最初のアプローチ、a.k.a. DataTemplatesを使用する場合に発生します。同じことが、バインドされたソースアイテムとデータテンプレートと共にTabControlを使って起こります。 ViewModelは再作成されませんが、ビューはです。これを回避する唯一の方法は、ビューの作成方法を制御することです。これは、カスタムコントロールで行うことができます。 [ここ](http://stackoverflow.com/questions/3877611/is-it-possible-to-cache-the-view-when-using-model-first-approach)を参照してください。 – Michael

+0

代わりにContentControlを拡張することで、[this](http://stackoverflow.com/questions/9794151/stop-tabcontrol-from-recreating-its-children)を試すことができます。 – Michael

+0

その提案をありがとう。私はこの方法を行っていきます。 – kotsumu

答えて

0

ContentControlを拡張しても問題を解決できませんでした。私がこのアプローチを使用して遭遇した問題は、ContentControlの依存関係プロパティが直接的にはインタフェースできない/オーバーライドできないために、既存の依存関係プロパティをハックすることでした。また、DataTemplateの初期化は、単純なContentControlよりも深くなるようです。

私は、自分の見解が表示されているかどうかを単に変更することに決めました。このアプローチは、本質的に私の意見がバックグラウンドにとどまり、自分のことをして、いつでも元の状態に移行できるようにしたいからです。

1

これは古い問題ですが、私もこの問題に苦労していました。その答えは、ビューインスタンスをリソースに直接配置し、それらをデータテンプレートのコンテンツコントロールにバインドすることです。そうすると、ビューは一度だけインスタンス化されます。

<Window.Resources> 
    <views:FirstPanelView x:Key="FirstPanelViewKey"/> 
    <views:SecondPanelView x:Key="SecondPanelViewKey"/> 
    <DataTemplate x:Key="DT1"> 
     <ContentControl Content="{StaticResource FirstPanelViewKey}" /> 
    </DataTemplate> 
    <DataTemplate x:Key="DT2"> 
     <ContentControl Content="{StaticResource SecondPanelViewKey}" /> 
    </DataTemplate> 
</Window.Resources> 
関連する問題