一尘不染

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

c#

最新版本的MVVM Light note中,已表明MVVM Light现在提供“导航服务”。

但是我和我的朋友google无法找到如何使用它。

我可以看到可以向INavigationServiceServiceLocator 询问,因此可以看到如何询问到另一页,但是:

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

该库有任何官方文档吗?因为目前我发现它的编码很好并且可以正常工作,但是当我必须搜索如何使用它时,除了他的博客中有一些条目,我再也找不到一个文档/示例来说明如何使用它。这非常令人沮丧。我发现的唯一文档是this,我对Pluralsight不太熟悉,但似乎必须每月订阅一次(作为个人,试图在业余时间制作应用程序是不可能的) )。


阅读 1062

收藏
2020-05-19

共1个答案

一尘不染

是的,在其最新版本中进行了MvvmLight介绍,但是他们没有提供任何实现(您可以使用WP中的已实现,Metroapps等),但不幸的是,您需要自行实现,这里是我目前的做法它(信用NavigationServiceWpfNavigationService``Wpf

首先 创建您的导航界面MvvmLight INavigationService

public interface IFrameNavigationService : INavigationService
{
    object Parameter { get; }  
}

所述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
    }

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

其次 :在中viewmodellocator,将导航服务(SetupNavigation())初始化,以便可以在视图模型中使用它:

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);
 }

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

 public LoginViewModel(IFrameNavigationService navigationService)
 {
      _navigationService = navigationService; 
 }
...
_navigationService.NavigateTo("Notes",data);
..

编辑

在此仓库中可以找到一个明确的样本。

2020-05-19