How to implement custom navigation service in mvvmlight

断了今生、忘了曾经 提交于 2019-12-23 08:23:41

问题


I am not quite comfortable with the existing MVVMlight navigation interface methods and that is very minimal and I want to implement my very own navigational interface in which I can expose sophisticated methods that manipulates the navigational stack and integrate it with the MVVM light.

Any guidance on achieving this is very much appreciated

Update:

I would like to implement other transitions for movement between pages like page curl,flip,rotate etc


回答1:


Here's a full implementation example that would solve the problem by adding a new interface that fully replaces the one from MvvmLight and also allows you to choose whether to use animations or not. In this example, we add the ability to control whether the navigation should be animated or not:

Interface

public interface ICustomNavigationService
{
    string CurrentPageKey { get; }
    void GoBack(bool animate = true);
    void NavigateTo(string pageKey, bool animate = true);
    void NavigateTo(string pageKey, object parameter, bool animate = true);
}

Implementation

public class NavigationService : ICustomNavigationService
{
    private readonly Dictionary<string, Type> _pagesByKey = new Dictionary<string, Type>();
    private NavigationPage _navigation;
    public NavigationPage Navigation
    {
        get
        {
            return _navigation;
        }
    }
    public string CurrentPageKey
    {
        get
        {
            lock (_pagesByKey)
            {
                if (_navigation.CurrentPage == null)
                {
                    return null;
                }

                var pageType = _navigation.CurrentPage.GetType();

                return _pagesByKey.ContainsValue(pageType)
                    ? _pagesByKey.First(p => p.Value == pageType).Key
                    : null;
            }
        }
    }

    public void GoBack(bool animate = true)
    {
        _navigation.PopAsync(animate);
        MessagingCenter.Send<INavigationService>(this, "NAVIGATING");
    }

    public void NavigateTo(string pageKey, bool animate = true)
    {
        NavigateTo(pageKey, null, animate);
        MessagingCenter.Send<INavigationService>(this, "NAVIGATING");
    }

    public void NavigateTo(string pageKey, object parameter, bool animate = true)
    {
        lock (_pagesByKey)
        {
            if (_pagesByKey.ContainsKey(pageKey))
            {
                var type = _pagesByKey[pageKey];
                ConstructorInfo constructor;
                object[] parameters;

                if (parameter == null)
                {
                    constructor = type.GetTypeInfo()
                        .DeclaredConstructors
                        .FirstOrDefault(c => !c.GetParameters().Any());

                    parameters = new object[]
                    {
                    };
                }
                else
                {
                    constructor = type.GetTypeInfo()
                        .DeclaredConstructors
                        .FirstOrDefault(
                            c =>
                            {
                                var p = c.GetParameters();
                                return p.Count() == 1
                                       && p[0].ParameterType == parameter.GetType();
                            });

                    parameters = new[]
                    {
                        parameter
                    };
                }

                if (constructor == null)
                {
                    throw new InvalidOperationException(
                        "No suitable constructor found for page " + pageKey);
                }

                var page = constructor.Invoke(parameters) as Page;
                _navigation.PushAsync(page, animate);
            }
            else
            {
                throw new ArgumentException(
                    string.Format(
                        "No such page: {0}. Did you forget to call NavigationService.Configure?",
                        pageKey),
                    "pageKey");
            }
        }
    }

    public void Configure(string pageKey, Type pageType)
    {
        lock (_pagesByKey)
        {
            if (_pagesByKey.ContainsKey(pageKey))
            {
                _pagesByKey[pageKey] = pageType;
            }
            else
            {
                _pagesByKey.Add(pageKey, pageType);
            }
        }
    }

    public void Initialize(NavigationPage navigation)
    {
        _navigation = navigation;
    }

}

From here, you can add other methods you would like. Make sure to inject this or use it directly where you were using your MvvmLight one before.



来源:https://stackoverflow.com/questions/43243754/how-to-implement-custom-navigation-service-in-mvvmlight

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!