How to implement custom navigation service in mvvmlight
Asked Answered
A

1

7

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

Amoebic answered 6/4, 2017 at 0:30 Comment(10)
How do you mean integrate it with the MVVM light? You can just create your own ICustomNavigationService interface, implement it for the various OS's, and then register the implementation in the SimpleIoc container. If you are not that familiar how navigation is done in the different platforms you can look at the source code here mvvmlight.codeplex.com/SourceControl/latest and see how it is done by the author of MVVM lightGreater
Thanks for providing light on this ! Basically I have an app which already uses INavigationService which is in the shared code..its used by iOS,Android and windows app..now I just want to replace the iNavigation service with my own service which will have extra APIs providing access to the navigational stack .. is it possible if so how to do that ?Amoebic
You create a new interface, lets call it ISharathNavigationService, and define all needed operations. You use this interface in your shared code. Then you implement it on each platform; (WindowsNavigationService or similar) and register the implementation to the interface with the SimpleIoc container (like SimpleIoc.Default.Register<ISharathNavigationService, WindowsNavigationService>()). Finally in your shared code you call the SimpleIoc container for the instance of the ISharathNavigationService (similar to SimpleIoc.Default.GetInstance<ISharathNavigationService>())Greater
Thanks,Basically I want to create an interface where I will have access to my own navigation stack and I can provide access to the underlying navigational stack via Methods.If you could explain me how to do that its very much appreciated ! Showing an example or model would be very goodAmoebic
I would like to customize the transition of page push and pop tooAmoebic
can you be a bit more specific? Where are you stuck exactly? I know its a little work; I'd tackle this problem by looking at the source code from mvvm light to understand how navigation is done by the "pros", and then trying to implement it by myself by adding the stuff I additionally need. I'm sure there are already good resources for both iOS and Android how to modify the navigation stackGreater
I am navigating basically from this particular page... page_middle and pushing 4 pages one by one not in a single time based on user choice ...then I want to pop all four pages in one time but to achieve that I am calling four times go back and it looks awkward in UI transition point of view... If Call navigateTo(page_middle) then it creates one more instance of page_middle....so I am thinking to access the navigationstack which is a array and remove the last 4 pages one by one in array ...and leave the navigation stack with the page_middle as top item so it won't look bad in ui transitionAmoebic
if possible I want to show a transition of the push while removing the 4 pages and leaving it with page_middleAmoebic
I'd just recommend you start coding, it sounds like you know what you want to archive, and it sounds doable. I think you have enough to get started (for example the existing code from MVVM light).Greater
I am wondering if its possible .. I will start anyhowAmoebic
R
6

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.

Romanaromanas answered 10/4, 2017 at 20:28 Comment(7)
How to add push transition for pop ? or how to do other type of transition for example flip,rotate,pagecurl during push and pop process ?Amoebic
Now that's a completely different question. This example is just that - an example. This uses Xamarin.Forms navigation, which doesn't include extra animations for transitions, you would have to do that custom in a NavigationRenderer. The point of this example is to show how you can create a custom implementation of a custom interface, and use that in-place of the MvvmLight NavigationService. If you want special animations, you're going to have to write that yourself or ask a separate question from this.Romanaromanas
The custom animations for navigation has nothing to do with MvvmLight and its navigation service, but belongs to the responsibilities of the native platforms. If you want to customize that, you'll have to write some more custom code.Romanaromanas
Are you saying we can push an pop without transition animation in MVVM and we can apply transition aimation in native platforms... I don't understand how to do that . lets take xamarin.ios as example... navigation happens in view model but how will I able to apply transition animation from native side...please explainAmoebic
Please remember that stackoverflow is not a coding service. From the comments on your question, and from this example it should be doable for you to try to solve this problem for yourself now.Greater
@FlorianMoser - I tried myself and I don't know where to proceed for the different animation part.. if I could get some clues on how to do ... it'd be really greatAmoebic
Xamarin has demos for iOS navigation transitions here: developer.xamarin.com/samples/monotouch/TransitionsDemo If you follow their pattern, you can use it as an implementation in your custon navigation service.Romanaromanas

© 2022 - 2024 — McMap. All rights reserved.