示例#1
0
        public async Task Navigate(CancellationToken ct, INavigationRequest request)
        {
            await Task.Run(async() =>
            {
                var isReleased = false;
                await _semaphore.WaitAsync();
                try
                {
                    var pageDefinition = _pageDefinitions.GetPageDefinition(request.PageName);
                    var viewModel      = _viewModelFactory.ResolveViewModel(pageDefinition.ViewModelType);

                    //create tasks
                    var setDataContext      = SetPageDataContext(pageDefinition, viewModel).ToTask();
                    var navigatingTask      = NotifyNavigating(ct, pageDefinition, request);
                    var navigationIsStarted = await _dispatcherScheduler.Run(() => _frame.Navigate(pageDefinition.Uri));
                    if (!navigationIsStarted)
                    {
                        throw new InvalidOperationException("Navigation failed");
                    }

                    viewModel.Initialize(request);
                    await navigatingTask;
                    var pageElement = await setDataContext;
                    //since the navigation completed, we can let another navigation start
                    _semaphore.Release();
                    isReleased = true;

                    //add entry to history
                    var historyEntry = new AliveNavigationHistoryEntry(request, viewModel);
                    _history.Append(historyEntry);

                    //list to loaded / unloaded events
                    RegisterViewModelLoad(pageElement, viewModel);
                    RegisterViewModelUnload(pageElement, viewModel);
                }
                finally
                {
                    if (!isReleased)
                    {
                        _semaphore.Release();
                        isReleased = true;
                    }
                }
            });
        }