云后面是什么

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

wpf开发中使用mvvmlight navigation-service

新项目需要使用mvvmlight wpf完成,需要做到在多个view间跳转。

使用简单的消息实现了这个功能,但是遇到一个问题:MainView中显示FuncView1,第一次没有问题,但是FuncView1隐藏后(或者关闭),再一次显示它,上面的控件都不再可用,没有找到问题根源,所以无法解决,

现在想通过NavigationService来实现跳转,但坑爹的是mvvmlight中定义了INavigation, 但没有针对wpf的实现,只有自己来了。

first create you navigation interface that Implements the MvvmLight INavigationService

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

the Parameter is used to pass objects between ViewModels, and the INavigationService is part of GalaSoft.MvvmLight.Views namespace

then implemente that interface like so

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;}}}returnnull;}publiceventPropertyChangedEventHandlerPropertyChanged;protectedvirtualvoidOnPropertyChanged([CallerMemberName]string propertyName =null){PropertyChangedEventHandler handler =PropertyChanged;if(handler !=null) handler(this,newPropertyChangedEventArgs(propertyName));}#endregion}

the MainFrame in the above code is the x:Name of a simple Frame control Defined in Xaml used to navigate between pages (custom as your need)

Second: In the viewmodellocator, init your navigation service (SetupNavigation()), so you can use it in your 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);
        }


Third: finaly, use the service, for example

 public LoginViewModel(IFrameNavigationService navigationService)
        {
            _navigationService = navigationService; 
...
_navigationService.NavigateTo("Notes",data);
..
posted on 2017-04-27 14:24  云后面是什么  阅读(643)  评论(0)    收藏  举报