- Navigation by control switching.
- Navigationg to view by id.
- Multiplatform support.
- MVVM support with WPF and Xamarin.Forms provider.
- Parameter support between target.
- Stacked navigation support.
- Lifecycle event support.
- Cancel event support.
- Plugin support.
- Library integration support.
// Config Navigator
navigator = new NavigatorConfig()
.UseFormsNavigationProvider()
.UseResolver(resolver)
.UseIdViewMapper(m => m.AutoRegister(Assembly.GetExecutingAssembly().ExportedTypes))
.ToNavigator();
// Navigate to view
navigator.Forward(ViewId.Menu);
Package | Note |
---|---|
Core libyrary | |
Smart.Resolver integration | |
Xamarin.Forms provider | |
WPF provider | |
Windows Forms provider |
Control
is a container and Control
is a view.
navigator = new NavigatorConfig()
.UseControlNavigationProvider(ContainerPanel)
.ToNavigator();
ContentControl
is a container and Control
is a view.
navigator = new NavigatorConfig()
.UseWindowsNavigationProvider()
.ToNavigator();
<ContentControl>
<i:Interaction.Behaviors>
<navigation:NavigationContainerBehavior Navigator="{Binding Navigator}"/>
</i:Interaction.Behaviors>
</ContentControl>
ContentView
is a container and View
is a view.
navigator = new NavigatorConfig()
.UseFormsNavigationProvider()
.ToNavigator();
<ContentView>
<ContentView.Behaviors>
<navigation:NavigationContainerBehavior Navigator="{Binding Navigator}" />
</ContentView.Behaviors>
</ContentView>
Implement the following interface.
public interface INavigationProvider
{
// Resolve target(DataContext/BindingContext) from view
object ResolveTarget(object view);
// Add view to container
void OpenView(object view);
// Remove view from container and dispose
void CloseView(object view);
// Restore view from stack
void ActiveView(object view, object parameter);
// Deactive view
object DeactiveView(object view);
}
// Configuration method
NavigatorConfig UseIdViewMapper(Action<IIdViewRegister> action);
// Register interface
public interface IIdViewRegister
{
void Register(object id, Type type);
}
// Auto register extension
void AutoRegister(IEnumerable<Type> types);
// Usage
public enum ViewId
{
ViewList,
ViewDetailNew,
ViewDetailUpdate
}
[View(ViewId.ViewList)]
public sealed class ViewList
{
}
[View(ViewId.ViewDetailNew)]
[View(ViewId.ViewDetailUpdate)]
public sealed class ViewDetail
{
}
// config
var navigator = new NavigatorConfig()
.UseSomeProvider()
.UseIdViewMapper(m => m.AutoRegister(Assembly.GetExecutingAssembly().ExportedTypes))
.ToNavigator();
// navigation
navigator.Forward(ViewId.ViewList);
// Configuration method
NavigatorConfig UseDirectViewMapper();
// config
var navigator = new NavigatorConfig()
.UseSomeProvider()
.UseDirectViewMapper()
.ToNavigator();
// navigation
navigator.Forward(typeof(View1));
// Configuration method
NavigatorConfig UsePathViewMapper(Action<PathViewMapperOptions> action)
// Usage
namespace Example.Views
{
public sealed class ParentView
{
}
}
namespace Example.Views.Children
{
public sealed class Child1View
{
}
public sealed class Child2View
{
}
}
// config
var navigator = new NavigatorConfig()
.UseMockFormProvider()
.UsePathViewMapper(option =>
{
option.Root = "Example.Views";
option.Suffix = "View";
option.AddAssembly(Assembly.GetExecutingAssembly());
})
.ToNavigator();
// navigation
navigator.Forward("/Parent");
navigator.Forward("/Children/Child1");
navigator.Forward("Child2");
navigator.Forward("../Parent");
navigator.Forward("Children/Child2");
Non stacked navigation.
bool Forward(object id);
bool Forward(object id, INavigationParameter parameter);
Task<bool> ForwardAsync(object id);
Task<bool> ForwardAsync(object id, INavigationParameter parameter);
Stacked navigation.
bool Push(object id);
bool Push(object id, INavigationParameter parameter);
Task<bool> PushAsync(object id);
Task<bool> PushAsync(object id, INavigationParameter parameter);
Pop stack navigation.
bool Pop();
bool Pop(INavigationParameter parameter);
bool Pop(int level);
bool Pop(int level, INavigationParameter parameter);
Task<bool> PopAsync();
Task<bool> PopAsync(INavigationParameter parameter);
Task<bool> PopAsync(int level);
Task<bool> PopAsync(int level, INavigationParameter parameter);
Pop with Forward navigation.
bool PopAndForward(object id);
bool PopAndForward(object id, int level);
bool PopAllAndForward(object id);
bool PopAndForward(object id, INavigationParameter parameter);
bool PopAndForward(object id, int level, INavigationParameter parameter);
bool PopAllAndForward(object id, INavigationParameter parameter);
Task<bool> PopAndForwardAsync(object id);
Task<bool> PopAndForwardAsync(object id, int level);
Task<bool> PopAllAndForwardAsync(object id);
Task<bool> PopAndForwardAsync(object id, INavigationParameter parameter);
Task<bool> PopAndForwardAsync(object id, int level, INavigationParameter parameter);
Task<bool> PopAllAndForwardAsync(object id, INavigationParameter parameter);
Implement the following interface to create custom navigation.
public interface INavigationStrategy
{
// Initialize
StragtegyResult Initialize(INavigationController controller);
// Resolve next view
object ResolveToView(INavigationController controller);
// Stack update
void UpdateStack(INavigationController controller, object toView);
}
public interface INavigator
{
// Stack count
int StackedCount { get; }
// Current view id
object CurrentViewId { get; }
// Current view instance
object CurrentView { get; }
// Current target(DataContext/BindingContext or view itself) instance
object CurrentTarget { get; }
// Navigating status
bool Executing { get; }
}
public interface INavigationEventSupport
{
// From page event berfore stack changed
void OnNavigatingFrom(INavigationContext context);
// To page event berfore stack changed
void OnNavigatingTo(INavigationContext context);
// To page event after stack changed
void OnNavigatedTo(INavigationContext context);
}
INavigationContext
has navigation information.
public interface INavigationContext
{
object FromId { get; }
object ToId { get; }
NavigationAttributes Attribute { get; }
INavigationParameter Parameter { get; }
}
INavigationParameter
is navigation parameteter store.
public interface INavigationParameter
{
T GetValue<T>(string key);
T GetValue<T>();
T GetValueOrDefault<T>(string key);
T GetValueOrDefault<T>();
T GetValueOr<T>(string key, T defaultValue);
T GetValueOr<T>(T defaultValue);
}
NavigationAttributes
has the following extension methods.
public static class NavigationAttributesExtensions
{
public static bool IsStacked(this NavigationAttributes attributes);
public static bool IsRestore(this NavigationAttributes attributes);
}
public interface INavigator
{
// Cancel confirm event
event EventHandler<ConfirmEventArgs> Confirm;
// Navigating event before stack changed
event EventHandler<NavigationEventArgs> Navigating;
// Navigating event after stack changed
event EventHandler<NavigationEventArgs> Navigated;
// Navigator exit event
event EventHandler<EventArgs> Exited;
// Navigation executing changed event
event EventHandler<EventArgs> ExecutingChanged;
}
ConfirmEventArgs
is CancelEventArgs
with INavigationContext
.
public sealed class ConfirmEventArgs : CancelEventArgs
{
public INavigationContext Context { get; }
}
NavigationEventArgs
has INavigationContext
and view instance information.
public sealed class NavigationEventArgs : EventArgs
{
public INavigationContext Context { get; }
public object FromView { get; }
public object FromTarget { get; }
public object ToView { get; }
public object ToTarget { get; }
}
Cancel when false is returned.
public interface IConfirmRequest
{
bool CanNavigate(INavigationContext context);
}
public interface IConfirmRequestAsync
{
Task<bool> CanNavigateAsync(INavigationContext context);
}
Navigator external notification reception interface.
public interface INotifySupport
{
void NavigatorNotify(object parameter);
}
public interface INotifySupport<in T>
{
void NavigatorNotify(T parameter);
}
public interface INotifySupportAsync
{
Task NavigatorNotifyAsync(object parameter);
}
public interface INotifySupportAsync<in T>
{
Task NavigatorNotifyAsync(T parameter);
}
Notification method is as follows.
// Usage
navigator.Notyfy(parameter);
// Usage(Async)
await navigator.NotyfyAsync(parameter);
Navigator is injected.
public interface INavigatorAware
{
INavigator Navigator { get; set; }
}
Previous parameter is set next.
public sealed class View1
{
[Parameter]
public int IntParameter { get; set; }
}
public sealed class View2
{
[Parameter]
public int IntParameter { get; set; }
}
// Test
navigator.Forward(typeof(View1));
var view1 = (View1)navigator.CurrentView;
view1.IntParameter = 123;
navigator.Forward(typeof(View2));
var view2 = (View2)navigator.CurrentView;
Assert.Equal(123, view2.IntParameter);
- Set to property with same name.
- Even if the name of the property is different, it can be specified by attribute.
- I/O direction can be limited by
Directions.Import
/Directions.Export
. - When different types are converted by IConverter.
Inject object that exist between scopes.
public sealed class ScopeData : IInitializable, IDisposable
{
...
}
public sealed class Data1View
{
}
public sealed class Data2View
{
[Scope]
public ScopeData Data { get; set; }
}
public sealed class Data3View
{
[Scope]
public ScopeData Data { get; set; }
}
// Test
navigator.Forward(typeof(Data1View));
navigator.Forward(typeof(Data2View)); // ScopeDate create and initialized
var view2 = (Data2View)navigator.CurrentView;
navigator.Forward(typeof(Data3View));
var view3 = (Data3View)navigator.CurrentView;
Assert.Equal(view3.Data, view2.Data);
navigator.Forward(typeof(Data1View)); // ScopeData disposed
- Set to property with same name.
- Even if the name of the property is different, it can be specified by attribute.
- Supports
IInitializable
andIDisposable
lifecycle events.
Implement the following interface and register to NavigatorConfig.
public interface IPlugin
{
// Process when view created
void OnCreate(IPluginContext context, object view, object target);
// Process when view closed
void OnClose(IPluginContext context, object view, object target);
// Process before stack is changed
void OnNavigatingFrom(IPluginContext context, object view, object target);
// Process before stack is changed
void OnNavigatingTo(IPluginContext context, object view, object target);
// Process after stack is changed
void OnNavigatedTo(IPluginContext context, object view, object target);
}
IPluginContext is data store for plugin.
public interface IPluginContext
{
void Save<T>(Type type, T value);
T Load<T>(Type type);
T LoadOr<T>(Type type, T defaultValue);
T LoadOr<T>(Type type, Func<T> defaultValueFactory);
}
- Interface is used for object creation.
- Default implementation is
Activator.CreateInstance()
. - Customizable by creating the following implementation.
public interface IActivator
{
object Resolve(Type type);
}
Usa.Smart.Navigation.Resolver
provides an implementation of IActivator
using Usa.Smart.Resolver
.
// Usage
// Config Resolver
var resolver = CreateResolver();
// Config Navigator
navigator = new NavigatorConfig()
.UseSomeProvider()
.UseResolver(resolver)
.ToNavigator();
- Interface is used for type conversion.
- Default implementation uses
Smart.Converter.IObjectConverter
. - Customizable by creating the following implementation.
public interface IConverter
{
object Convert(object value, Type type);
}
- Animation support required (・ω・)?