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