I am working on a Windows Phone application, here is the scenario that I have problem:
So I have three pages, lets call it page 1, 2, 3.
In page 1, I have a button called start downloading. Click the button and use NavigateService.Navigate(page2Uri) and navigate to page2.
Page 2 makes query and downloads images from internet, so in its OnNavigateTo handler, I check the page back stack, if it is navigated from page 1, I will do the download. In the app bar of this page, I have a button that can navigate to page3.
Page 3 is a list of options that will perform some behavior on the image that is downloaded in page2. Once I choose an option, I want to go back to page 2 and perform some behavior on the loaded image.Here the question comes: if I use NavigateService.Navigate(page2Uri) to navigate from page3 to page2, it will call the Page2 constructor and OnNavigateTo handler again, which will cause it to lose every instance variable it already got.
But if I use NavigatService.GoBack it will go back to page2, then realizes that the backstack top entry is page1 (since page1 -> page2 -> page3). So it will re-download everything again.
I dont want anything to be downloaded again when navigate back form page3 to page2. So wondering if anyone has good idea about this.
Thank you.
You can use the query parameters and NavigationEventArgs to help.
First, you can use the NavigationEventArgs to determine if the user is going forward or background by checking the NavigationMode.
Second, you can tell page 2 to download by using the query parameters.
From page1:
private void MoveToPage2FromPage1()
{
NavigationService.Navigate(new Uri("/Page2.xaml?shouldDownload=true", UriKind.Relative));
}
and page2:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (e.NavigationMode == NavigationMode.Back) return;
string shouldDownload = ""; //May not be needed if you'll only ever go to page 2 from page 1 to download...
if (NavigationContext.QueryString.TryGetValue("shouldDownload", out shouldDownload))
{
Convert.ToBoolean(shouldDownload);
}
}
There are several ways to pass data to another page:
You can use query parameters as Shawn suggested.
You can use global data stored somewhere like in app.cs
You can use a static class to hold the data.
You can use a shared viewModel to hold the parameters. (or static properties in the viewmodel)
It all depends on the particular case. I think Shawns suggestion of using query paramaters is probably the most 'correct' MVVM way, but the other methods have their place.
You need to implement the following function and the navigation service.
These code will definitely solve your problem
for two or more parameters, use this code
String download="true";
String file="image";
NavigationService.Navigate(new Uri("/Page3.xaml?download="+download+"&file="+file+"", UriKind.Relative));
OnNavigatedTo, add the following code on to your Page2
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
String download=NavigationContext.QueryString["download"];
String file=NavigationContext.QueryString["file"];
}
For the above OnNavigatedTo function outputs true and image. You can use MessageBox.Show(); to output
Related
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.
For an outside of the box idea on a particular site I'm building, I would like to use a drop down list control, which has two inputs: Sponsor1 and Sponsor2. My goal is that when a visitor chooses one of the options, they will go a page for that particular sponsor, and enter a pre-defined code via a textbox w/ a "Next" button, which will take them to yet another page to enter more info.
I'm sort of dividing the site up to have branches, as the sponsors will have visitors (i.e., customers) and the sponsors can keep track of these visitors via the input that will go to a database yet to be made.
As I'm creating this in Asp.Net/C#, I cannot find any examples of this being done, outside an old reference being done with JavaScript - yet the end concept is not the same:
Creating a drop-down list that links to other pages
So is this possible to code something in C# within the code-behind to make this behave as I wish, or must I scrap this idea and just do it another way? Thanks to all in advance!!
Have you tried calling an event when the user selects something on the drop-down list?
Edit: Added more context to where everything goes.
protected override void OnInit(EventArgs)
{
dropDownList.selectedIndexChanged += new EventHandler(ddlIndexChanged);
base.OnInit(ea);
}
//Your Page_Load Here
private void ddlIndexChanged(object sender, EventArgs ea)
{
//This is called when the index is changed, you could redirect here
}
I have an application for Windows 8 with a page (Frame) for displaying a list of items and a page for downloading & displaying the items details. I am also using MVVM Light for sending notifications.
Application use goes something like this:
Open Main Page
Navigate to List Page
Frame.Navigate(typeof(MyPage));
Choose Item
//Complete logic
Frame.GoBack();
Back on Main Page, I start downloading the file in the view model, I send ONE NotificationMessage saying BeginDownloadFile and after it is downloaded ONE NotificationMessage saying EndDownloadFile.
The first time I do steps 2,3, & 4 my NotificationReceived method is hit once, the second twice and so forth.
private async void NotificationMessageReceived(NotificationMessage msg)
{
if (msg.Notification == Notifications.BeginDownloadFile)
{
FileDownloadPopup.IsOpen = true;
}
else if (msg.Notification == Notifications.EndDownloadFile)
{
FileDownloadPopup.IsOpen = false;
}
}
Additional information: I only have one FileDownloadPopup, yet each time, an additional popup is shown each time the NotificationMessageReceived method is called.
My only conclusion is that between navigating forwards and backwards in my app, there are multiple MainPages being created and never closed. This results in many NotificationsMessageReceived methods just waiting for a notification to come their way so they can show their popup.
I have two questions:
1. Does this sound like normal behaviour for a Windows 8 app?
2. How can I close all instances of the MainPage or return to the previous instance without creating a new instance?
Please let me know if I have missed something important out before marking my question down.
This sounds normal to me. The default navigation behaviour in Windows 8 is to create a new page instance each time you navigate to a new page, regardless of whether this is forward or back navigation.
Try setting the NavigatinCacheMode on MainPage to Required. See the MSDN documentation for details of how page caching works.
It sounds like you are registering eventhandlers in the page and then not removing them. Each time you navigate to the page again the handler is being added again in addition to the one you previously added. Try to add your event handler in OnNavigatedTo, and make sure you unregister it in OnNavigatedFrom.
protected override void OnNavigatedTo(Windows.UI.Xaml.Navigation.NavigationEventArgs e)
{
MyEvent.OnDownloadRequest += MyLocalDOwnloadHandler; // add the handler
}
protected override void OnNavigatedFrom(Windows.UI.Xaml.Navigation.NavigationEventArgs e)
{
MyEvent.OnDownloadRequest -= MyLocalDOwnloadHandler; // remove the handler
}
As you can see, I want to navigate to "ScoreInputDialog.xaml" page, where the user can type in a name. After this I am trying to save the name to a list, but it is always empty because navigation to page "ScoreInputDialog.xaml" is being done at last. How can I navigate to the desired page and get my value before continuing with rest of the code?
NavigationService.Navigate(new Uri("/ScoreInputDialog.xaml", UriKind.Relative)); // Sets tempPlayerName through a textbox.
if (phoneAppService.State.ContainsKey("tmpPlayerName"))
{
object pName;
if (phoneAppService.State.TryGetValue("tmpPlayerName", out pName))
{
tempPlayerName = (string)pName;
}
}
highScorePlayerList.Add(tempPlayerName);
You should do nothing directly after the Navigate call. Instead override the OnNavigatedTo method of the page you are coming from, to get notified when the user comes back:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
This method will be called when the user exits the "ScoreInputDialog.xaml", probably by pressing the back button or because you call NavigationService.GoBack(). This exits the "ScoreInputDialog.xaml" page and goes to the previous page, where the OnNavigatedTo will be called. This is the time to check for the value.
Illustration of the navigation flow:
"OriginPage" ---[Navigate]---> "ScoreInputDialog" ---[GoBack() or Back-button]---> "OriginPage" (*)
Where the (*) is there the OnNavigatedTo will be called. The implementation could look like this:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
if (phoneAppService.State.ContainsKey("tmpPlayerName"))
{
object pName;
if (phoneAppService.State.TryGetValue("tmpPlayerName", out pName))
{
tempPlayerName = (string)pName;
}
highScorePlayerList.Add(tempPlayerName);
}
}
Remember to clear the temp player name before calling Navigate:
phoneAppService.State.Remove("tmpPlayerName");
NavigationService.Navigate(new Uri("/ScoreInputDialog.xaml", UriKind.Relative));
Note: OnNavigatedTo will also be called when the user sees the page the first time or navigates back from other pages than "ScoreInputDialog.xaml". But then the "tmpPlayerName" value will not be set.
Navigate isn't being performed last, it is just happening asynchronously. You have to wait for the navigation to complete.
http://msdn.microsoft.com/en-us/library/system.windows.navigation.navigationservice.navigated.aspx
Read the following page : http://msdn.microsoft.com/en-us/library/ms615507.aspx
At the bottom after the Methods and Properties definitions in the "Remark" part it explains how the NavigationService Class works and this nice little graphic explains a lot :
For example, I want a button to take me to a settings page, and then back to the main screen. Just as an example for me to understand the workflow. Any guidance?
I use the NavigationService to navigate to the new page, where the Uri has a path relative to the project's base directory.
private void OptionsMenuItem_Click(object sender, EventArgs e)
{
// Navigate to the new page
NavigationService.Navigate(new Uri("/Views/OptionsView.xaml", UriKind.Relative));
}
The back button on the phone will take the user back to the previous page automatically, or you could code you own return button using the NavigationService again.
Dr. Herbie's method works great.
Another option is to implement INavigate on your PhoneApplicationPage. Then use a HyperlinkButton. If you have a lot of buttons and don't want to write a bunch of click handlers, this can be more convenient.
Your implementation of INavigate.Navigate just uses the page's NavigationService like this:
public bool Navigate(Uri source)
{
NavigationService.Navigate(source);
return true;
}
You must take care of certification requirements! Look at this tutorial: http://www.yourwindowsphone7.com/tutorials/navigation-in-windows-phone-7-apps.html