2016-07-19 12 views
1

Ich habe zwei DataTemplates, die abhängig vom aktuellen ViewModel geschaltet werden. Jedes Mal, wenn ich mein ViewModel umschalte, scheint es den Konstruktor der jeweiligen View aufzurufen und ruft den Aufruf InitializeComponent() im Konstruktor auf, was bedeutet, dass immer dann, wenn ich das DataTemplate umschalte, eine neue View erzeugt, die an das entsprechende DataTemplate gebunden ist. Ich bin mir nicht sicher, warum dies passiert, aber gibt es eine Möglichkeit, die Erstellung einer neuen Ansicht beim Wechseln von ViewModels zu verhindern?MVVM - Datatemplate erstellt eine neue Ansicht

Unten finden Sie die DataTemplates, die sich in meinem MainView befinden.

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

Die Vorlage wird in einem ContentControl angezeigt.

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

Das ist mein SecondPanelView die die gleiche wie meine FirstPanelView ist, ist es sehr einfach ist.

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

Mein Ioc sicher macht, dass ich nur eine Instanz des

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

Datacontext SecondPanelView generieren wird durch einen speziellen Markup-Erweiterung in jeder Ansicht begrenzt ist.

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

Das ruft nur GetInstance des jeweiligen ViewModel.

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

Dies ist von Entwurf in WPF. Wenn eine Ansicht den Gültigkeitsbereich verlässt, wird die Ansicht zerstört und muss neu erstellt werden, wenn sie erneut angezeigt werden muss. Dies geschieht, wenn Sie ViewModel first approach, a.k.a. DataTemplates verwenden. Das Gleiche passiert mit einem TabControl mit verknüpften Quellelementen und Datenvorlagen. Auch wenn das ViewModel nicht neu erstellt wird, ist die Ansicht. Die einzige Möglichkeit, dies zu umgehen, besteht darin, Kontrolle darüber zu haben, wie die Ansicht erstellt wird. Dies kann in einem benutzerdefinierten Steuerelement erfolgen. Siehe [hier] (http://stackoverflow.com/questions/3877611/is-it-possible-to-cache-the-view-when-using-model-first-approach). – Michael

+0

Sie könnten [this] (http://stackoverflow.com/questions/9794151/stop-tabcontrol-from-recreating-its-children) versuchen, aber stattdessen ein ContentControl erweitern. – Michael

+0

Danke für diesen Vorschlag. Ich werde diese Methode ausprobieren. – kotsumu

Antwort

0

Ich war nicht in der Lage, mein Problem zu lösen, selbst nach der Erweiterung von ContentControl. Das Problem, auf das ich bei diesem Ansatz stieß, war, dass die Abhängigkeitseigenschaft von ContentControl nicht direkt interfacable/overridable war, was mich zwang, auf die vorhandene Abhängigkeitseigenschaft zu hacken. Auch die Initialisierung eines DataTemplate scheint tiefer zu fallen als das einfache ContentControl.

Also entschied ich mich, die Art zu ändern, in der meine Ansichten angezeigt werden, indem ich einfach ihre Sichtbarkeit ändere. Dieser Ansatz hat für mich funktioniert, da ich im Grunde genommen möchte, dass meine Ansichten im Hintergrund bleiben und ihr eigenes Ding machen und bereit sind, in jedem Moment in ihrem vorherigen Zustand zu interagieren.

1

Dies ist ein altes Problem, aber ich hatte auch mit diesem Problem zu kämpfen. Die Antwort besteht darin, die View-Instanzen direkt in den Ressourcen zu platzieren und sie an Inhaltssteuerelemente in den Datenvorlagen zu binden. Wenn Sie dies tun, wird die Ansicht nur einmal instanziiert.

<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>