I have two questions here about Windows Phone page navigation:
Is there a way to get the instance of the page I am navigating to? That is, if I am on page one and want to navigate to page2 to when button click, can I get the page2 instance after page2 is initialized by NavigationService.Navigate("page_2_uri") call in page 1?
Is there a way I can know which page I navigate from? For example, I am currently on page3, and I want to do something like: if page 3 is navigated from page 2, I will do this, otherwise I will do that.
Thank you.
Is there a way to get the instance of the page I am navigating to?
No.
Is there a way I can know which page I navigate from?
Yes. Traverse the NavigationService.BackStack
The idea for using the NavigationService to navigate between pages is that you don't need to know any details about your destination. So in your example, Page 2 isn't initialized until you've left Page 1, and therefore Page 1 is no longer in scope, and won't be able to do anything with Page 2. If you want to pass information/context to Page 2, id recommend using Query Parameters (see next answer). If you want to know where the navigation is going, you can override the OnNavigatedFrom event and look at the Uri property of the NavigationEventArgs.
I would recommend looking at the NavigationContext property of the Silverlight Page class. This property lets you view the QueryString of the navigation request. Using this approach, you could navigate to page 3 using a uri like "page_3?previous_page=2" and then extract the previous_page from the QueryString of the NavigationContext to see where you came from.
Related
I am trying to determine which was the previous page for current page in .NET MAUI application.
For example, there are 3 pages Page1, Page2, Page3
When going from Page1 to Page2, in Page2, I would like to access PreviousPage property which gives me "Page1" as value.
When going from Page3 to Page2, in Page2, PreviousPage property gives me "Page3" as value.
^^
However, I can only see "PreviousPage" property member in Debug mode when VS hits breakpoint. I cannot access it in code. Intellisense does not show this too.
How can I access and use this "PreviousPage" in my code? Is there any other way?
See screenshot.
I am using:
Microsoft Visual Studio Community 2022 (64-bit) - Preview
Version 17.5.0 Preview 1.0
Thank you.
https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/shell/navigation?view=net-maui-7.0
Navigation events
The Shell class defines the Navigating event, which is fired when navigation is about to be performed, either due to programmatic navigation or user interaction. The ShellNavigatingEventArgs object that accompanies the Navigating event provides the following properties...
Technically you can implement your own custom logic, to see if something has been loaded, what was source, the navigation paths, etc...
Your requirement can be achieved with minimum amount of code.
However, I do not think that navigation stack is a healthy way to check if something is displayed on your page or not.
You could get all the page in Navigation Stack, simply used:
var stack = Application.Current.MainPage.Navigation.NavigationStack;
int count = Application.Current.MainPage.Navigation.NavigationStack.Count;
The current page is the last one, names (count - 1) index (as it is zero-based index) in the stack, so the previous page is (count - 2) index.
Hope it works for you.
Like #h-a-h mentioned, custom logic was the way.
I implemented sort of workaround to make it work. I used navigation parameters.
My viewmodel constructor has attribute like this:
[QueryProperty("IsBack", "IsBack")]
public class Page2ViewModel
{
//called from code-behind on OnNavigatedTo event using associated Command.Execute
async Task LoadData()
{
if(IsBack == false)
{
await _repos.GetListAsync();
}
}
public bool IsBack {get;set;}
}
When going from Page1 to Page2, I do:
await Shell.Current.GoToAsync($"{nameof(View.Page2)}?IsBack={false}");
When going back to Page2 from Page3, I do:
await Shell.Current.GoToAsync($"..?IsBack={true}");
At least this way I know "when" Page2 is visited so as to prevent loading of data again. Though this does not let me know if I am coming back to Page2 from Page3 or Page'n', it solves my current requirement.
One can always use query parameters to provide the parent page.
e.g., from Page5 to Page2, we can do:
await Shell.Current.GoToAsync($"..?IsBack={true}&ParentPageId={nameof(View.Page5)}");
provided Page2's ViewModel has this QueryParameter attribute.
[QueryProperty("ParentPageId", "ParentPageId")]
Not very elegant but workable.
Thank you all for your help.
I'm developing a WP 8 app and I've a problem with navigation.
I can't find a way to navigate to a page on my back stack without losing my actual page state.
The situation is this:
I'm on page A and navigate to page B, so the back stack only contains A.
On page B I want to navigate back to page A but with page B being persisted on the back stack, so when I'm on page A again I can go back to page B preserving it state.
So this is it: A --> B --> A --> B, it's kind of a cycle but it isn't one. Page A shows items that are also shown in page B with less detail, but from page B I can go to page A to see the details and then back and back again.
It may seem complicated but I assure you its pretty intuitive :) it works like this on Android and iOS.
Is there anyway to add page B to the navigation stack before page A so when I call NavigationService.GoBack() it goes back to page A with it previous state and then do the same from A to B.
Thanks in advance!!!
There are a couple of options. If you use the standard MVVM pattern then you're not really saving "page state" (unless you mean things like scroll position in lists or selected text control) - you're saving data. And that data will be there the next time you navigate to Page B. You can watch this video and the MSDN article it points to for more information on databinding and how to store the data in global state that will be re-bound to the page the next time you navigate.
If databinding doesn't solve the problem, another option is to not use different pages at all, but to just have A and B as two different containers on the same physical page. You can then trap the back button to fake going "back" when you need to toggle back to Container A.
Use this help topic to learn how to preserve and restore page state for Windows Phone 8. Navigation stack can store only page URI and a small amount of data (in the URI parameter).
Like this:
NavigationService.Navigate(new Uri("/SecondPage.xaml?var=value", UriKind.Relative));
At the SecondPage.xaml you can get the value of val. Here is detailed example.
if (NavigationContext.QueryString.TryGetValue("val", out msg))
I've something that I can't get myself understand. I'm making an app with databound template. I put a textbox on mainpage and a button. when i type something in textbox and press on button it navigates to the listing page and that content comes from web and then if i press on back button and make a new search the results from previous search stays there. how can i reset/clear or disable cache of that page?
It would be helpful if you could post your XAML and code-behind, but I will attempt to make a jab at an answer. Where are you referencing the call to get the data from the web? If it is in the constructor of the page, then that is why the previous search stays there. What is probably happening is the first search constructs the secondary page, does your web call, and binds your data to the page. Then when you press the back button, and click it again, the page is already constructed, so it uses the same data.
It is probably wise to call your web service in the OnNavigatedTo override method. From the first page, you can pass parameters to your secondary page (i.e., pass the search term, then pass the search term into your web service).
Here is an example of passing parameters between pages: http://developer.nokia.com/Community/Wiki/Passing_parameters_while_navigating_between_pages_on_Windows_Phone
Also, make sure your Data Context for the second page is appropriately set each time the page is navigated to, since you have a data bound application.
Without code, I can't really help other than giving these things to think about.
I am working on a simple Windows Phone app, which has basically those functionality:
Page 1, there is a button to get user's location, and navigate to page 2
Page 2, use the user location and map control to display a map and view center is user's location. There is a app bar button to navigate to Page 3.
Page 3, Show some nearby place list in this page, and once user select one of the places, it will go back to page 2 to Pin the place on Map Control.
So here is the question: I want to keep page 2 data alive in this case so I dont have to re-initialize page 2 everytime I go back from page 3. It would be perfect I can keep an instance of page 2 somewhere, and use that everytime I want to come back from page 3. So far I know there are two approach, one is in Page2 xaml I can have something like:
<Page
x:class "Page2.keepPageAlive"
...
The other one is using AddBackEntry. But I am not sure which one is fit in my case, or is there any other good approach.
Please share your idea, thank you.
As long as you navigate to page3 from page2, and go back to page2 using NavigationService.GoBack(), the page2 instance will be kept alive. So you basically have nothing to change.
In the WP7 Navigation stack, Page 2 will still exist. So if you navigated from Page 1 to Page 2 to Page 3, all 3 pages exist.
If you call NavigationService.GoBack() from Page 3, it will pop Page 3 off and restore the previous instance of Page 2, not create a new instance of Page 2. This is also what happens when you hit the Back button.
Only if you call NavigationService.Navigate() would a new instance be created.
Platform:
Silverlight 4 / .NET 4
Background:
I have a page that consists of two parts. The left part is a tree view, the right one is the content area. When I select a tree item, an appropriate UserControl page should be loaded in the right part of the page, depending on the type of the tree item.
I am using a Frame object, defined in XAML.
When a user selects a tree view item, I resolve the item's type and then I navigate to the page defined for that type.
However, Frame.Navigate is an asynchronous method so if I try to get the frame's content after Navigate, the frame has not navigated yet, so I either get nothing or the last loaded page.
contentFrame.Navigate(new Uri("/PageA.xaml", UriKind.Relative));
PageA page = contentFrame.Content as PageA;
// page here is either null or a previously opened page
Problem:
I need to send some data (stored in treeview item's Tag) to the page being navigated to and the only Frame.Navigate overload is asynchronous (without callback). How can I send some data to the navigated page? Is there any other technique for accomplishing what I need?
You can use the NavigationService provided by Silverlight. It has query string support using which you can build RESTful URI. I am assuming that you need to pass some context based data to the landing page. Following links might help you
http://www.silverlightshow.net/items/The-Silverlight-3-Navigation-Framework.aspx
http://blogs.microsoft.co.il/blogs/alex_golesh/archive/2009/04/02/silverlight-3-quick-tip-6-navigation-framework-and-uri-routing.aspx
http://www.wintellect.com/CS/blogs/jprosise/archive/2009/04/07/silverlight-3-s-new-navigation-framework.aspx
Although the links says Silverlight 3, these features are supported in Silverlight 4 as well.
You definitely want to use some flavor of the M-V-VM pattern that Nilesh suggested.
I guess you could also have a static class that holds static references of objects.
You can simply refer to static objects here when your frames have completed their event (e.g. NavigatedTo).