NavigationView does not switch with page cache enabled/required - c#

In the first page I have a navigation view and have enabled page cache on this page. Without pushing any other page on this, I can switch between tabs. But once I navigate to a new page and then pop back the navigation stops working. If I disable the cache all of the state is lost which I dont want. Tried setting it to required too. The pages are not heavy I tested by creating a sample app with just a textblock.
<Page
...
NavigationCacheMode="Required">
# Navigation View goes here
</Page>
In the page pushed on top of the main navigation page, I have below code to dismiss the page.
private void OnCloseClick(object sender, RoutedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame.CanGoBack) { rootFrame.GoBack(); }
}
Once gone back the navigation simply does not work, what am I doing wrong here ?

Stumbled across the same problem and looks like there's a bug in NavigationView class. Long story short, it is not able to properly recover after Load-Unload-Load cycle (e.g. when it is removed from and added back to view hierarchy - which happens when you navigate from page and back) and stops working.
Update: Checked with NavigationView from WindowsUI SDK. Works like a charm, only settings item seems to be broken yet it still has a problem with selecting items with SelectsOnInvoked set to false (aka conditional select).

Related

Wpf navigation frame inside a frame, navigation button are disabled in child

I have into solution
(A) wpf user control project (library dll): this has an user control which has a frame, own navigation buttons and a menu to navigate between some Pages which are also defined in this project.
(B) wpf application (test): I used to test the dll. It has only a main window which has uses the user control defined in the previous project.
(C) wpf application (let's say the final project) which is more complex. This has also a frame with own navigation button and own menu. The frame has to show several pages defined in this project and also the user control of A.
When I use (B) to test (A) everything works fine.
When I use (C) to show (A) the navigation button of A are disabled, and instead the navigation button of C works for pages of A and C.
It looks that the all the commands sent to the frame of C are instead sent to the parent frame of A.
How is it possible?
I have my navigation button with custom UIRoutedCommand
private void Backward_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = ChildFrame?.CanGoBack??false;
e.Handled = true;
}
ChildFrame?.CanGoBack is always false when A is used by C.
Maybe I wrote the question too fast, instead of read MSDN documentation...
<Frame x:Name="ChildFrame" NavigationUIVisibility="Hidden" JournalOwnership="OwnsJournal">
JournalOwnership="OwnsJournal" saved my day

Xamarin.Forms Prism - Using navigation service to navigate from one detail page to another

In my Xamarin.Forms Prism app, I am using a MasterDetailPage for navigation.
While I am on one detail page, I would like to navigate to another detail page, as if I had selected it from the master page.
Initial navigation in App.xaml.cs:
protected override void OnInitialized()
{
...
NavigationService.NavigateAsync("MainPage/RootNavigation/MyFirstPage");
}
When I click a shortcut button on MyFirstPage, I would like to go to MainPage/RootNavigation/MySecondPage. The closest that I have been able to achieve has been using an absolute Uri.
private async void OnShortcutTapped(MyModel sender)
{
...
await _navigationService.NavigateAsync(new Uri("http://myapp.com/MainPage/RootNavigation/MySecondPage", UriKind.Absolute), navigationParams, null, false);
}
This basically gets me what I want, but after navigating in this manner, if I make the Master visible and select the menu item for MySecondPage, it refreshes the detail page as if it is navigating to the page.
Is there a better way to maintain this navigation, so that the master page knows that MySecondPage is already being displayed and it doesn't try to reload it?
While your navigation pattern doesn't make a lot of sense to me, you can achieve what you want by invoking a navigate command in the MasterDetailPageViewModel. You have a number of ways to do this. You could use the IEventAggregator to send a message to the MasterDetailPageViewModel to navigate, or you can use a CompositeCommand that invokes a DelegateCommand that exists on the MasterDetailPageViewModel.
You can see a sample of using a CompositeCommand here: https://github.com/PrismLibrary/Prism-Samples-Forms/tree/master/UsingCompositeCommands
You can also see how to send messages in this sample that I gave at the Xamarin Evolve conference: https://github.com/brianlagunas/Evolve2016SamplesAndSlides
Another option would be to just call a navigate command off the App.Current.MainPage ViewModel from with your MyFirstPage code behind.

Navigating between views in Windows 10 XAML

I've tried a number of approaches to this, but when trying to navigate between one page and another in Windows 10 I'm getting some strange behaviour. I display my first page in app.xaml.cs:
View.MainPageView mp = new View.MainPageView();
Window.Current.Content = mp;
This displays the main page fine; however, I have a command that does effectively the same thing for my second page:
View.SecondView dv = new View.SecondView();
Window.Current.Content = dv;
What happens is that it displays the second page, but it is blank. When I try to inspect it using XAML Spy, it shows that the page is there; however, there is no content for it at all (that is, no controls showing).
Is there something particular about Windows 10 that might explain this or, alternatively, is there something about overriding the content in this way that might explain this behaviour?
EDIT:
It appears that the issue is caused by using a bound command, rather than a handled even in order to navigate; the following code works on a click event:
Frame rootFrame = Window.Current.Content as Frame;
rootFrame.Navigated += RootFrame_Navigated;
rootFrame.Navigate(typeof(View.SecondView), null);
But when called from a bound command, whilst it still shows the view, it is always blank. I initially thought this might be relating to the calling thread, but using the UI thread dispatcher makes no difference.
Windows 10 uses the same approach like 8.1.
If you create a new project in Visual Studio and open App.xaml.cs you can find there OnLaunched method. Inside this method you can see that instance of Frame is created and assigned to Window.Current.Content. Frame will help you to manage whole navigation. At the end of this method is navigation to the MainPage.
rootFrame.Navigate(typeof(MainPage), e.Arguments);
If you want to navigate to the second page from the main page, you have to use:
Frame.Navigate(typeof(SecondPage));
In order to go back to the main page just call:
if (Frame.CanGoBack)
{
Frame.GoBack();
}

How to update Cached Page from an Asyn Task After Navigating to another Page?

I am Navigating from a Page to another page when a background downloading work is going on.
In the Page 1, I'm updating a progress bar based on the progress received.
I've cached Page1 before Navigating to Page 2.
But when We Navigate back to Page1, the View is not updated even if we have updated Model and Notified it using MVVM method. But W've verified that the progress is completed and the file is downloaded.
We are using the below code to cache Page.
this.NavigationCacheMode = NavigationCacheMode.Enabled;
I am wondering why the View is not updated, even if we have tried to update it. If we are not Navigating to another page, the progress is updated. So We are sure that it will work on normal case except on caching.
Please help on this situation.
clearing cache should help you
override the following in your caller page
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
if (e.Uri.ToString().Contains("/target"))
{
Frame parentFrame = (Frame) Parent;
var cacheSize = parentFrame.CacheSize;
parentFrame.CacheSize = 0;
parentFrame.CacheSize = cacheSize;
}
base.OnNavigatingFrom(e);
}
replace /target with your intended url or replace the condition with your own logic eg. after you update your view model or both
idea behind is to see when we are navigating to the cached target then we set the cache size of the frame to 0 which will effectively clear the cache and then restore back the original limit to start caching again.
Note this method is effective for NavigationCacheMode.Enabled only it may not work for NavigationCacheMode.Required as it is more difficult to clear.
Finally I come to a workaround solution. I found that while Navigating back, only PageLoad is invoked again. So I kept all Tasks to be loaded at PageLoad in the Page constructor after the
this.InitializeComponent();
And it turned out to be a workaround for my scenario.

How to properly navigate backstack in Windows Phone 8.1 universal store app

Here's the scenario for my page navigation:
MainPage (MP) <==> Locations (L) <==> AddLocation (AL)
I don't want the user to ever go to AddLocation when hitting the back button on the phone.
If they are on MP and they hit back, they should exit the app.
If they went MP->L and hit back, they should go to MainPage.
If they went MP->L->AL and hit back, they should go to Locations.
If they went MP->L->AL->L and hit back, they should go to MainPage and not back to AddLocations.
Right not, I have the standard nav helpers in the Common folder and then I've added this code to the Locations page to make this happen:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.navigationHelper.OnNavigatedTo(e);
var bs = Frame.BackStack.Where(b => b.SourcePageType.Name == "MainPage").FirstOrDefault();
if (bs!= null)
{
Frame.BackStack.Clear();
Frame.BackStack.Add(bs);
}
}
This seems to be a terrible hack to me and I'm sure there some supported/designed way to do this that I don't know about. I'm very new to WinRT and Xaml.
Your problem is went MP->L->AL->L and hit back, they should go to MainPage and not back to AddLocations isn't it?
The solution is: when you finish adding location, you should go to Locations Page from AddLocation Page.
But you should not use Frame.Navigate(typeof(LocationPage)); to do this.
You should use Frame.GoBack();, So AddLocation Page will be removed from BackStack auto.

Categories

Resources