MVVM Light 5.0:如何使用导航服务

J4N*_*J4N 18 c# wpf mvvm mvvm-light

最新版本的MVVM Light note中,已经表明MVVM Light现在提供了"导航服务".

但我和我的朋友谷歌无法找到如何使用它.

我可以看到我可以向INavigationServiceServiceLocator 询问,所以我看到我可以要求转到另一个页面,但是:

  1. 我创建了一个新的窗口,我希望为"页面"保留一个特定的区域,我该如何指定?
  2. 如何指定所有可用页面?有什么我应该打电话的吗?
  3. 给出的参数格式是什么? INavigationService

这个图书馆有官方文件吗?因为目前我发现它很好地编码并且工作正常,但是当我要搜索如何使用它时,我从来没有找到如何使用的文档/示例,除了他的博客有一些条目.这非常令人沮丧.我找到的唯一文件就是这个,我对Pluralsight不太熟悉,但似乎必须每月订阅一次(作为个人,试图在我的空闲时间申请,是不可能的).

Sam*_*Dev 34

是的,MvvmLight介绍了NavigationService他们的最后一个版本,但他们没有提供任何实施Wpf(你可以使用NavigationServiceWP,Metroapps中的Implemented,..)但不幸的是Wpf,你需要自己实现,在这里我目前如何做它(信用)

首先创建实现的导航界面MvvmLight INavigationService

public interface IFrameNavigationService:INavigationService
    {
        object Parameter { get; }  
    }
Run Code Online (Sandbox Code Playgroud)

所述Parameter用于传递之间的物体ViewModels,并且INavigationService是其一部分GalaSoft.MvvmLight.Views的命名空间

然后实现这样的界面

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
    }
Run Code Online (Sandbox Code Playgroud)

MainFrame上面的代码是x:名称的简单的Frame定义在控制Xaml使用的页面(根据您的需求定制)之间导航

第二:在viewmodellocator初始化你的导航服务(SetupNavigation()),你可以在你的viewmodels中使用它:

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);
        }
Run Code Online (Sandbox Code Playgroud)

第三:最后,使用服务,例如

 public LoginViewModel(IFrameNavigationService navigationService)
        {
            _navigationService = navigationService; 
...
_navigationService.NavigateTo("Notes",data);
..
Run Code Online (Sandbox Code Playgroud)

编辑

可以在此回购中找到明确的样本.

  • 是的,通过使用 _navigationService.Parameter,您可以在 ViewModel 之间获取传递的对象,只需在所有 ViewModel 的 Ctor 中传递 IFrameNavigationService。您可以更改 GoBack 方法以接受将传递给前一个 View 的 GoBack(Object parameter) 参数。 (2认同)
  • [NotifyPropertyChangedInvocator]只是一个Resharper属性,对吗? (2认同)
  • 请问我如何从_navigationService.NavigateTo("Notes",data)的接收ViewModel获取返回的对象/值; (2认同)