Newer
Older
SubCabinetSolution / SubCabinetSolution / Utils / NavigationService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Views;
using SubCabinetSolution.Views;

namespace SubCabinetSolution.Utils
{
    public class NavigationService : ViewModelBase, INavigationService
    {
        private readonly Dictionary<string, Uri> _pagesByKey;
        private readonly List<string> _historic;
        private string _currentPageKey;

        #region Properties

        public string CurrentPageKey
        {
            get => _currentPageKey;

            private set { Set(() => CurrentPageKey, ref _currentPageKey, value); }
        }

        public object Parameter { get; private set; }

        #endregion

        #region Ctors and Methods

        public NavigationService()
        {
            _pagesByKey = new Dictionary<string, Uri>();
            _historic = new List<string>();
        }

        public void GoBack()
        {
            if (_historic.Count <= 1) return;
            _historic.RemoveAt(_historic.Count - 1);

            NavigateTo(_historic.Last(), "Back");
        }

        public void NavigateTo(string pageKey)
        {
            NavigateTo(pageKey, "Next");
        }

        public virtual void NavigateTo(string pageKey, object parameter)
        {
            lock (_pagesByKey)
            {
                if (!_pagesByKey.ContainsKey(pageKey))
                {
                    throw new ArgumentException($@"No such page: {pageKey} ", nameof(pageKey));
                }

                // 设置应用主窗口,name要注意和xaml保持一致
                var cabinetWindow = Application.Current.Windows
                    .Cast<Window>()
                    .FirstOrDefault(window => window is CabinetWindow) as CabinetWindow;
                if (GetDescendantFromName(cabinetWindow, "CabinetFunctionFrame") is Frame frame)
                {
                    frame.Source = _pagesByKey[pageKey];
                }

                Parameter = parameter;
                if (parameter.ToString().Equals("Next"))
                {
                    _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++)
            {
                if (!(VisualTreeHelper.GetChild(parent, i) is FrameworkElement frameworkElement)) continue;
                if (frameworkElement.Name == name)
                {
                    return frameworkElement;
                }

                frameworkElement = GetDescendantFromName(frameworkElement, name);
                if (frameworkElement != null)
                {
                    return frameworkElement;
                }
            }

            return null;
        }

        #endregion
    }
}