Async Navigation Service
See original GitHub issueI’ve written an async version of INavigationService
and related classes which I’d like to contribute back to the project:
IAsyncNavigationService.cs
using System;
using System.Threading.Tasks;
using System.Windows.Navigation;
namespace MyApp.Mvvm.Navigation
{
/// <summary>
/// Temporary async version of <see cref="Caliburn.Micro.INavigationService"/>.
/// </summary>
public interface IAsyncNavigationService
{
#region Properties
/// <summary>
/// Indicates whether the navigator can navigate back.
/// </summary>
bool CanGoBack { get; }
/// <summary>
/// Indicates whether the navigator can navigate forward.
/// </summary>
bool CanGoForward { get; }
/// <summary>
/// The current content.
/// </summary>
object CurrentContent { get; }
#endregion
#region Events
/// <summary>
/// Raised after navigation.
/// </summary>
event NavigatedEventHandler Navigated;
/// <summary>
/// Raised prior to navigation.
/// </summary>
event NavigatingCancelEventHandler Navigating;
/// <summary>
/// Raised when navigation fails.
/// </summary>
event NavigationFailedEventHandler NavigationFailed;
/// <summary>
/// Raised when navigation is stopped.
/// </summary>
event NavigationStoppedEventHandler NavigationStopped;
/// <summary>
/// Raised when a fragment navigation occurs.
/// </summary>
event FragmentNavigationEventHandler FragmentNavigation;
#endregion
#region Methods
/// <summary>
/// Navigates to the view represented by the given view model.
/// </summary>
/// <param name="viewModel">The view model to navigate to.</param>
/// <param name="extraData">Extra data to populate the view model with.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
Task NavigateToViewModelAsync(Type viewModel, object extraData = null);
/// <summary>
/// Navigates to the view represented by the given view model.
/// </summary>
/// <typeparam name="TViewModel">The view model to navigate to.</typeparam>
/// <param name="extraData">Extra data to populate the view model with.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
Task NavigateToViewModelAsync<TViewModel>(object extraData = null);
/// <summary>
/// Stops the loading process.
/// </summary>
void StopLoading();
/// <summary>
/// Navigates back.
/// </summary>
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
Task GoBackAsync();
/// <summary>
/// Navigates forward.
/// </summary>
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
Task GoForwardAsync();
/// <summary>
/// Removes the most recent entry from the back stack.
/// </summary>
/// <returns> The entry that was removed. </returns>
JournalEntry RemoveBackEntry();
#endregion
}
}
AsyncNavigationHelper.cs
using Caliburn.Micro;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;
namespace MyApp.Mvvm.Navigation
{
/// <summary>
/// Builds a Uri in a strongly typed fashion, based on a ViewModel.
/// </summary>
/// <typeparam name="TViewModel"></typeparam>
public class NavigationHelper<TViewModel>
{
#region Fields
readonly Dictionary<string, object> m_QueryString = new Dictionary<string, object>();
IAsyncNavigationService m_NavigationService;
#endregion
#region Public Methods
/// <summary>
/// Adds a query string parameter to the Uri.
/// </summary>
/// <typeparam name="TValue">The type of the value.</typeparam>
/// <param name="property">The property.</param>
/// <param name="value">The property value.</param>
/// <returns>Itself</returns>
public NavigationHelper<TViewModel> WithParam<TValue>(Expression<Func<TViewModel, TValue>> property, TValue value)
{
if (value is ValueType || !ReferenceEquals(null, value))
{
m_QueryString[property.GetMemberInfo().Name] = value;
}
return this;
}
/// <summary>
/// Attaches a navigation servies to this builder.
/// </summary>
/// <param name="navigationService">The navigation service.</param>
/// <returns>Itself</returns>
public NavigationHelper<TViewModel> AttachTo(IAsyncNavigationService navigationService)
{
m_NavigationService = navigationService;
return this;
}
/// <summary>
/// Navigates to the Uri represented by this builder.
/// </summary>
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
public async Task NavigateAsync()
{
if (m_NavigationService == null)
{
throw new InvalidOperationException("Cannot navigate without attaching an IAsyncNavigationService. Call AttachTo first.");
}
await m_NavigationService.NavigateToViewModelAsync<TViewModel>(m_QueryString);
}
#endregion
}
}
AsyncNavigationExtensions.cs
namespace MyApp.Mvvm.Navigation
{
/// <summary>
/// Extension methods related to navigation.
/// </summary>
public static class NavigationExtensions
{
#region Properties
/// <summary>
/// Creates a Uri builder based on a view model type.
/// </summary>
/// <typeparam name="TViewModel">The type of the view model.</typeparam>
/// <param name="navigationService">The navigation service.</param>
/// <returns>The builder.</returns>
public static NavigationHelper<TViewModel> For<TViewModel>(this IAsyncNavigationService navigationService)
{
return new NavigationHelper<TViewModel>().AttachTo(navigationService);
}
#endregion
}
}
Issue Analytics
- State:
- Created 4 years ago
- Comments:6 (4 by maintainers)
Top Results From Across the Web
c# - NavigationService.Navigate async behaviour
Created a window and a page which contains one button. Now on click of that button, i am navigating to another page using...
Read more >NavigationService.Navigate Method (System.Windows. ...
Navigate asynchronously to source content located at a URI, pass an object containing navigation state for processing during navigation, and sandbox the content ......
Read more >Up and running with React Navigation | by Daniel Merrill
When you tell the navigator to navigate to 'Home', this is how it'll know what to do. Initialize your navigator with the config...
Read more >Create async versions of INavigateAsync.RequestNavigate
The implementation of navigation service will look for both interfaces and, if any of them is implemented, use it. For existing programs that ......
Read more >Asynchronous Jobs | Adobe Experience Manager
You can view the status of asynchronous jobs from the Background Operations dashboard at Global Navigation -> Tools -> General -> Jobs.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@neilt6 Make it a method then.
bool CanGoBackAsync()
@popcatalin81 I disagree with your suggestion, as I don’t believe properties should ever be async. To quote MSDN Magazine:
IMHO in a properly designed navigation service,
CanGoBack
andCanGoForward
should just retrieve cached values that are updated inNavigateToViewModelAsync()
,GoBackAsync()
, andGoForwardAsync()
.