Dans la dernière version de MVVM Light note , il a été indiqué que MVVM Light fournit désormais un "service de navigation".
Mais moi et mon ami google sommes incapables de trouver comment l'utiliser.
Je peux voir que je peux demander une INavigationService
à ServiceLocator, je vois donc comment je peux demander de passer à une autre page, mais:
INavigationService
Existe-t-il une documentation officielle pour cette bibliothèque? Parce qu'actuellement, je le trouve bien codé et fonctionne bien, mais quand j'ai à chercher comment l'utiliser, je ne trouve jamais de documentation/exemple montrant comment faire, à l'exception de son blog qui a une entrée. C'est très frustrant. La seule documentation que j'ai trouvée est ceci , je ne connais pas très bien Pluralsight, mais il me semble qu'il est obligatoire de souscrire un abonnement mensuel n'est pas possible).
Oui, MvvmLight
a introduit la NavigationService
dans sa dernière version mais elle n’a proposé aucune implémentation concernant Wpf
(vous pouvez utiliser la version implémentée NavigationService
dans WP, Metroapps, ..), mais malheureusement pas Wpf
, vous devez l’implémenter par vous-même, voici comment je le fais actuellement ( crédit )
first crée votre interface de navigation qui implémente la MvvmLight
INavigationService
public interface IFrameNavigationService:INavigationService
{
object Parameter { get; }
}
Parameter
est utilisé pour passer des objets entre ViewModels
, et INavigationService
fait partie de l'espace de noms GalaSoft.MvvmLight.Views
puis implémenter cette interface comme si
class FrameNavigationService : IFrameNavigationService,INotifyPropertyChanged
{
#region Fields
private readonly Dictionary<string, Uri> _pagesByKey;
private readonly List<string> _historic;
private string _currentPageKey;
#endregion
#region Properties
public string CurrentPageKey
{
get
{
return _currentPageKey;
}
private set
{
if (_currentPageKey == value)
{
return;
}
_currentPageKey = value;
OnPropertyChanged("CurrentPageKey");
}
}
public object Parameter { get; private set; }
#endregion
#region Ctors and Methods
public FrameNavigationService()
{
_pagesByKey = new Dictionary<string, Uri>();
_historic = new List<string>();
}
public void GoBack()
{
if (_historic.Count > 1)
{
_historic.RemoveAt(_historic.Count - 1);
NavigateTo(_historic.Last(), null);
}
}
public void NavigateTo(string pageKey)
{
NavigateTo(pageKey, null);
}
public virtual void NavigateTo(string pageKey, object parameter)
{
lock (_pagesByKey)
{
if (!_pagesByKey.ContainsKey(pageKey))
{
throw new ArgumentException(string.Format("No such page: {0} ", pageKey), "pageKey");
}
var frame = GetDescendantFromName(Application.Current.MainWindow, "MainFrame") as Frame;
if (frame != null)
{
frame.Source = _pagesByKey[pageKey];
}
Parameter = parameter;
_historic.Add(pageKey);
CurrentPageKey = pageKey;
}
}
public void Configure(string key, Uri pageType)
{
lock (_pagesByKey)
{
if (_pagesByKey.ContainsKey(key))
{
_pagesByKey[key] = pageType;
}
else
{
_pagesByKey.Add(key, pageType);
}
}
}
private static FrameworkElement GetDescendantFromName(DependencyObject parent, string name)
{
var count = VisualTreeHelper.GetChildrenCount(parent);
if (count < 1)
{
return null;
}
for (var i = 0; i < count; i++)
{
var frameworkElement = VisualTreeHelper.GetChild(parent, i) as FrameworkElement;
if (frameworkElement != null)
{
if (frameworkElement.Name == name)
{
return frameworkElement;
}
frameworkElement = GetDescendantFromName(frameworkElement, name);
if (frameworkElement != null)
{
return frameworkElement;
}
}
}
return null;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
la MainFrame
dans le code ci-dessus est le x: nom d'un simple contrôle Frame
défini dans Xaml
utilisé pour naviguer entre les pages (personnalisez-le en fonction de vos besoins)
Second: Dans la viewmodellocator
, lancez votre service de navigation (SetupNavigation()
) afin que vous puissiez l'utiliser dans vos modèles de vue:
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SetupNavigation();
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<LoginViewModel>();
SimpleIoc.Default.Register<NoteViewModel>();
}
private static void SetupNavigation()
{
var navigationService = new FrameNavigationService();
navigationService.Configure("LoginView", new Uri("../Views/LoginView.xaml",UriKind.Relative));
navigationService.Configure("Notes", new Uri("../Views/NotesView.xaml", UriKind.Relative));
SimpleIoc.Default.Register<IFrameNavigationService>(() => navigationService);
}
Troisième: enfin, utilisez le service, par exemple
public LoginViewModel(IFrameNavigationService navigationService)
{
_navigationService = navigationService;
...
_navigationService.NavigateTo("Notes",data);
..
MODIFIER
Un exemple explicite peut être trouvé à ce repo .
Je ne sais pas si une fonctionnalité de navigation est disponible dans mvvm light. Je l'ai implémenté avec une liaison contentControl:
<xcad:LayoutDocumentPane>
<xcad:LayoutDocument x:Name="DetailDoc" CanClose="False">
<ContentControl Content="{Binding DisplayedDetailViewModel}"/>
</xcad:LayoutDocument>
</xcad:LayoutDocumentPane>
Et puis la propriété viewmodel. Il hérite de la classe ViewModelBase light de mvvm.
public ViewModelBase DisplayedDetailViewModel
{
get
{
return displayedDetailViewModel;
}
set
{
if (displayedDetailViewModel == value)
{
return;
}
displayedDetailViewModel = value;
RaisePropertyChanged("DisplayedDetailViewModel");
}
Pour que le contrôle de contenu sache quel contrôle utilisateur il doit utiliser, vous définissez DataTemplates dans app.xaml:
<Application.Resources>
<ResourceDictionary>
<!--
We define the data templates here so we can apply them across the
entire application.
The data template just says that if our data type is of a particular
view-model type, then render the appropriate view. The framework
takes care of this dynamically. Note that the DataContext for
the underlying view is already set at this point, so the
view (UserControl), doesn't need to have it's DataContext set
directly.
-->
<DataTemplate DataType="{x:Type viewModel:LoggerViewModel}">
<views:LogView />
</DataTemplate>
Le LogView est le UserControl. Vous devez simplement affecter LoggerViewModel à DisplayedDetailViewModel, et Framework effectuera le travail.