Jaki jest najlepszy sposób na przełączanie views / usercontrols w MVVM-light i WPF?

Jestem stosunkowo nowy w WPF i MVVM i najtrudniejszą rzeczą, jaką znalazłem, jest to, jak po prostu przełączyć usercontrol lub widok w aplikacji.

W winforms, aby Kontrola sama się usunęła, można by tak po prostu powiedzieć.Rodzic.Sterowanie.Remove (this);

W WPF nie ma ogólnej kontroli nadrzędnej, trzeba by ją wpisać do określonego typu (np. Grid), a następnie usunąć.

To również wydaje się łamać architekturę MVVM. I wypróbowałem również szablony danych i prezenterów treści, które działają dobrze, z wyjątkiem faktu, że nie mogę zmienić datacontext z kodu, ponieważ datacontext jest zawsze viewmodellocator.

Czy strony są teraz akceptowalnym sposobem na to w WPF? Co jeśli miałem siatkę z niestandardowym kontrolerem usecontrol i chciałem ją przełączyć na podstawie jakiejś zmiennej w viewModel? Wydaje się, że najprostszych zadań nie można łatwo wykonać w WPF.

Author: JReed, 2011-05-24

1 answers

Zrobiłbyś to w widoku rodzica.

Na przykład, jeśli Twoja strona (nazwij ją PageViewModel) miała dwa widoki (ViewModelA i ViewModelB), masz właściwość PageViewModel o nazwie CurrentView, która określiłaby, który Widok jest widoczny. Gdy PageViewModel.CurrentView jest ustawiona na instancję ViewModelA, to do rysowania zawartości jest używana płyta DataTemplate ViewA. Gdy jest ustawiona na instancję ViewModelB, wyświetlana jest tablica danych ViewB.

<DataTemplate DataType="{x:Type local:PageViewModel}">
    <ContentControl Content="{Binding CurrentView}" />
</DataTemplate>

<DataTemplate DataType="{x:Type local:ViewModelA}">
    <TextBlock Text="I'm ViewModelA" />
</DataTemplate>

<DataTemplate DataType="{x:Type local:ViewModelB}">
    <TextBlock Text="I'm ViewModelB" />
</DataTemplate>

Idealnie byłoby wywołać polecenie switch views z widoku nadrzędnego (w tym przypadku DataTemplate dla PageViewModel), jednak jeśli chcesz przełączać widoki z viewmodela/B, możesz ręcznie podłączyć zdarzenie podczas tworzenia obiektów (CurrentView.ChangeViewCommand = this.ChangeViewCommand) lub zajrzeć do systemu wiadomości. MVVM Light ma prostą Messenger klasę, którą znalazłem dość łatwą w użyciu, lub Prism ma bardziej zaawansowaną EventAggregator

Jeśli chcesz zmienić widok dla tego samego ViewModel, polecam właściwość Mode, która zostanie użyta do określenia, którego widoku użyć. Na przykład:

<DataTemplate x:Key="ViewA" DataType="{x:Type local:MyViewModel}">
    <TextBlock Text="I'm ViewModelA" />
</DataTemplate>

<DataTemplate x:Key="ViewB" DataType="{x:Type local:MyViewModel}">
    <TextBlock Text="I'm ViewModelB" />
</DataTemplate>

<DataTemplate DataType="{x:Type local:MyViewModel}">
    <ContentControl Content="{Binding }">
        <ContentControl.Style>
            <Style TargetType="{x:Type ContentControl}">
                <Setter Property="ContentTemplate" Value="{StaticResource ViewA}" />
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Mode}" Value="2">
                        <Setter Property="ContentTemplate" Value="{StaticResource ViewB}" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ContentControl.Style>
    </ContentControl>
</DataTemplate>

EDIT

Widzę, że tego typu pytania pojawiają się często, więc zamieścił coś na ten temat tutaj jeśli ktoś jest zainteresowany

 34
Author: Rachel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-10 19:35:17