Sextant icon indicating copy to clipboard operation
Sextant copied to clipboard

Routing API revamp RFC

Open mteper opened this issue 9 years ago • 3 comments

I just started experimenting with routing (UWP app), so while I have fresh eyes, some thoughts:

Rename RoutingState to Router

"Routing state" implies a container of state data rather than a class responsible for navigation actions. "Router" seems a better name for a class that actually handles routing. This is further reinforced by the fact that even on the IScreen interface, the RoutingState property name is "Router". IMO, Router is both more apt and concise.

Formalize navigation stack into a class

Today, we have a handful of commands hanging off RoutingState along with a ObservableCollection called "NavigationStack" (note that here it's not even a stack in the data structures sense of the term). It would be better to introduce a new class, NavigationStack with the following signature:

public class NavigationStack
{
  ReactiveCommand<Unit> Advance { get; }
  ReactiveCommand<Unit> Backtrack { get; }
  IRoutableViewModel Current { get; }
}

This would leave no ambiguity about what the commands do. If there is value in it, the class can implement ObservableCollection <IRoutableViewModel> to enable subscribing to notifications. Router would then have a read-only property named NavigationStack.

Replace the Navigate command with method + property

Is there value in Navigate being a command? Writing router.Navigate.Execute(vm) feels clunky. Would be better to have Navigate be a method, and have a companion Navigating observable property on Router. Another benefit is that the method can have an (optional) bool reset attribute, thus letting us drop the NavigateAndReset command on Router.

mteper avatar May 05 '16 00:05 mteper

👍 A lot of this is in line with my thoughts on re-vamping routing, perhaps for V8. However, I'd prefer stack semantics for NavigationStack members, such as Push and Pop.

But that's pretty much irrelevant minutia right now. I think the important thing is to take routing in a direction that gives us:

  • far greater consistency across platforms (by sharing far more code and pushing more responsibility into that shared code)
  • far greater flexibility (not dictating so much about how routing occurs at the UI level)
  • a story for platforms that aren't VM-first friendly (e.g. Android)

These are difficult problems to solve, and I think we should look for inspiration elsewhere (Prism, MVVMCross etc).

kentcb avatar May 20 '16 04:05 kentcb

When revamping navigation, I would also like something like Router.PushDialog.

This is a common scenario (I think), when I want edit an item in another ViewModel and then fall back to previous VM with new value.

Rigth now I use some hacks like this:

 EditItem = ReactiveCommand.CreateFromObservable<Item, Item>(item =>
            {


                var editVM = new EditItemViewModel(HostScreen, resolver, item);
                HostScreen.Router.Navigate.Execute(editVM).Subscribe();

                
               
                return HostScreen.WhenAnyValue(x => x.CurrentViewModel)
                        .Where(x => x == this)
                        .Take(1)
                        .TakeUntil(HostScreen.Router.NavigationStack.ShouldReset)
                        .Select(x => item);

                // or use EditDone command of EditVM

                return editVM.EditDone.Select(x => item)
                       .Take(1)
                       .TakeUntil(HostScreen.Router.NavigationStack.ShouldReset); 
                 // and navigate back in EditItem.Subscribe
});

I think that with NavigationStack it would be great to write something like this:

return HostScreen.Router.PushDialog.Execute(editVM).Select(x => item);

PushDialog would return editVM when Router.Pop would bring us back to CurrentViewModel and handle all edge cases of navigating to terminate returned observable.

It's quite easy to make an extension method for that, but if you want to revamp the whole thing either way, it could be just built-in functionality.

If there is already a easy way to make it error free, please tell me :)

qrzychu avatar Apr 10 '18 11:04 qrzychu

Assigning to @RLittlesII I know he's been wanting to get his feet dirty on this type of thing.

glennawatson avatar Sep 01 '18 00:09 glennawatson