ja naprawdę nie lubię, gdy referencje ViewModel Odwiedzin nawigować. Więc wolę podejście oparte na ViewModelu. Korzystając z ContentControls, DataTemplates for ViewModel typy & pewnego rodzaju wzór nawigacji w moim ViewModels.
Moja nawigacji wygląda następująco:
[ImplementPropertyChanged]
public class MainNavigatableViewModel : NavigatableViewModel
{
public ICommand LoadProfileCommand { get; private set; }
public ICommand OpenPostCommand { get; private set; }
public MainNavigatableViewModel()
{
LoadProfileCommand = new RelayCommand(() => Navigator.Navigate(new ProfileNavigatableViewModel()));
OpenPostCommand = new RelayCommand(() => Navigator.Navigate(new PostEditViewModel { Post = SelectedPost }),() => SelectedPost != null);
}
}
My NavigatableViewModel wygląda następująco:
[ImplementPropertyChanged]
public class NavigatableViewModel
{
public NavigatorViewModel Navigator { get; set; }
public NavigatableViewModel PreviousViewModel { get; set; }
public NavigatableViewModel NextViewModel { get; set; }
}
I moim Navigator:
[ImplementPropertyChanged]
public class NavigatorViewModel
{
public NavigatableViewModel CurrentViewModel { get; set; }
public ICommand BackCommand { get; private set; }
public ICommand ForwardCommand { get; private set; }
public NavigatorViewModel()
{
BackCommand = new RelayCommand(() =>
{
// Set current control to previous control
CurrentViewModel = CurrentViewModel.PreviousViewModel;
},() => CurrentViewModel != null && CurrentViewModel.PreviousViewModel != null);
ForwardCommand = new RelayCommand(() =>
{
// Set current control to next control
CurrentViewModel = CurrentViewModel.NextViewModel;
},() => CurrentViewModel != null && CurrentViewModel.NextViewModel != null);
}
public void Navigate(NavigatableViewModel newViewModel)
{
if (newViewModel.Navigator != null && newViewModel.Navigator != this)
throw new Exception("Viewmodel can't be added to two different navigators");
newViewModel.Navigator = this;
if (CurrentViewModel != null)
{
CurrentViewModel.NextViewModel = newViewModel;
}
newViewModel.PreviousViewModel = CurrentViewModel;
CurrentViewModel = newViewModel;
}
}
Moja MainWindows.xaml:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewmodels="clr-namespace:MyApp.ViewModels"
x:Class="MyApp.Windows.MainWindow"
mc:Ignorable="d"
Title="MainWindow" Height="389" Width="573"
d:DataContext="{d:DesignInstance {x:Type viewmodels:MyAppViewModel}, IsDesignTimeCreatable=True}">
<Grid>
<!-- Show data according to data templates as defined in App.xaml -->
<ContentControl Content="{Binding Navigator.CurrentViewModel}" Margin="0,32,0,0" />
<Button Content="Previous" Command="{Binding Navigator.BackCommand}" Style="{DynamicResource ButtonStyle}" HorizontalAlignment="Left" Margin="10,5,0,0" VerticalAlignment="Top" Width="75" />
<Button Content="Next" Command="{Binding Navigator.ForwardCommand}" Style="{DynamicResource ButtonStyle}" HorizontalAlignment="Left" Margin="90,5,0,0" VerticalAlignment="Top" Width="75" />
</Grid>
</Window>
App.xaml.cs:
public partial class App
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
new MainWindow {DataContext = new MyAppViewModel()}.Show();
}
}
MyAppViewModel:
[ImplementPropertyChanged]
public class MyAppViewModel
{
public NavigatorViewModel Navigator { get; set; }
public MyAppViewModel()
{
Navigator = new NavigatorViewModel();
Navigator.Navigate(new MainNavigatableViewModel());
}
}
App.xaml:
<DataTemplate DataType="{x:Type viewmodels:MainNavigatableViewModel}">
<controls:MainControl/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewmodels:PostEditViewModel}">
<controls:PostEditControl/>
</DataTemplate>
Minusem jest to, że masz więcej ViewModel kod, który zarządza stan tego, na co patrzysz. Ale oczywiście jest to także ogromna zaleta pod względem Testability. Oczywiście modele ViewModels nie muszą zależeć od Twoich widoków.
Plus Używam Fody/PropertyChanged, o to chodzi w [ImplementPropertyChanged]. Nie pozwala mi pisać kodu OnPropertyChanged.
Czy sprawdziłeś usługę nawigacyjną? –
używasz światła mvvm do swojej aplikacji? – SWilko
Nie, nie jestem dellywheel. – Mathias