In my windows phone 8 app, I am navigating among pages. say
From MainPage(some user control a click to) -> Page1 then with a key press it will take me to main page back again
From MainPage(some user control b click to) -> Page2 and then back with the key press to main page again and so on to page3, page4 etc.
Here I want to identify from which page the main page is loaded from?
Say page1, page2 or page3 based on that I want to load the user controls according to navigation history.
I could not found any built-in property or function in a library.
Any help, I am looking for best practice as well to achieve such functionality.
You can use back stack for this kind of purposes.
How to navigate using the back stack for Windows Phone
See also:
https://stackoverflow.com/a/7000977/942286
make hashtable global.
Hashtable ht = new Hashtable();
ht.Add("page1");
NavigationService.Navigate(new Uri("Page1.xaml", UriKind.Relative));
You can create an
enum PageType
{
NONE,
PAGE_1,
PAGE_2,
PAGE_3,
PAGE_4
}
Then in your MainPage you can have a ivar as
private PageType pageType = PageType.NONE;
Then when you move to a page you can set it
pageType = PageType.PAGE_!;
NavigationService.Navigate(new Uri("Page1.xaml", UriKind.Relative));
and when you come back to MainPage then you can have this
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.NavigationMode == NavigationMode.Back)
{
switch (pageType)
{
case PageType.NONE:
//Your code
break;
case PageType.PAGE_1:
//Your code
break;
case PageType.PAGE_2:
//Your code
break;
case PageType.PAGE_3:
//Your code
break;
case PageType.PAGE_4:
//Your code
break;
}
}
}
EDIT
You can then use navigation context.
In your user control
NavigationService.Navigate(new Uri("Page1.xaml?PAGE_TYPE=Page1", UriKind.Relative));
In your MainPage
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.NavigationMode == NavigationMode.Back)
{
String pageType = null;
NavigationContext.QueryString.TryGetValue("PAGE_TYPE", out pageType);
if (pageType == "Page1")
{
//Your code
}
}
}
If you must know what page you came from, you can use PhoneApplicationService.Current.State. Within your secondary pages, override OnBackKeyPress and set the value
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
base.OnBackKeyPress(e);
PhoneApplicationService.Current.State["LastPage"] = this;
}
Then in the MainPage, you would override OnNavigatedTo and check the value of the state
protected override void OnNavigatedTo(NavigationEventArgs e)
{
object lastPage;
if((e.NavigationMode == NavigationMode.Back) &&
(PhoneApplicationService.Current.State.TryGetValue("LastPage", out lastPage)))
{
// we navigated back and we know what the last page was!
var pageName = lastPage.GetType().Name;
if (pageName == "Page1")
{
// do something!
}
}
}
Just pass parameters when you are navigating back to main page, maybe an enum type contains 'page1' 'page2' ...
It seems that the NavigationService doesn't contain the information you need, as well as the NavigatingCancelEventArgs parameter coming with OnNavigatingFrom.
So unfortunately, it seems there's no builtin feature addressing your need.
However , what you could do is to persist the last page your user has been (to handle tombstoning scenarios). For instance it could be in AppSettings, here is a pseudo code :
public class WhateverYouWantLastPagePersister
{
private const string LastPageID = "LastPage";
public string GetLastPage()
{
string lastPage = string.Empty;
IsolatedStorageSettings.ApplicationSettings.TryGetValue<string>(LastPageID, out lastPage);
return lastPage;
}
public void PersistLastPage(string lastPage)
{
IsolatedStorageSettings.ApplicationSettings[LastPageID] = lastPage;
}
}
To persist "automatically" your last visited page, you can derive from PhoneApplicationPage and override OnNavigatingFrom to create a your own base page :
public class BasePage : PhoneApplicationPage
{
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
Uri currentUri = ((App)Application.Current).RootFrame.CurrentSource;
WhateverYouWantLastPagePersister.PersistLastPage(CustomMethodToExtractPageNameFromUri(currentUri));
}
}
All pages needing to persist the last visited pages have to derived from it (so Page1, Page2...)
Finally you can use WhateverYouWantLastPagePersister.GetLastPage() to get what you need.
Of course, in these pseudo code samples :
lastPage can be of any type you want (string, enum , int and so
on...), you just need an appropriate custom converter from string to anything you want
CustomMethodToExtractPageNameFromUri is a simple string parser
WhateverYouWantLastPagePersister can be static class, a singleton, injected with a DI framework, it's up to you!
Related
How can I extend the class Content Page to create a method that executes when it is the user's first time on a page?
(Xamarin.Forms)
This is probably the simplest way to do it:
public abstract class CustomContentPage : ContentPage
{
private bool _appeared;
protected override void OnAppearing()
{
base.OnAppearing();
if (!_appeared)
{
OnFirstAppearing();
_appeared = true;
}
}
protected abstract void OnFirstAppearing();
}
First you will want to use Application.Properties dictionary so you can preserve the state of the application, i.e. whether the user has ever gone to the page.
So in the OnAppearing method override in your ContentPage subclass, check to see if you have set the property in the Application.Current.Properties dictionary to see if the page has been visited. If the key is not present, set it and do whatever you want for this first visit to the page. If the key is present, do whatever you want to do for subsequent visits to the page, e.g.:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
if (!Application.Current.Properties.ContainsKey("main_page_visited"))
{
Application.Current.Properties["main_page_visited"] = true;
label.Text = "First Time visited";
}
else
{
label.Text = "Second+ Time visited";
}
}
}
The Application.Current.Properties gets saved automatically when the app exits.
I have a question and I can not find the right terms to do a reasoned search and solve the question.
Let's see, when I'm creating a page, at some point I need to create a WebUserControl and defer something like state = "true" (like the text of the lables) inside the html tag so that as soon as the page loads , Whether or not that control is subsequently edited in code.
<MyControls:Teste Id="aaa" runat="server" state="false"/>
The test control code is as follows: (The HTML page of this control is blank, it only has the header)
public partial class WebUserControls_WUC_Tect : System.Web.UI.UserControl
{
private static bool state ;
public bool State
{
get { return state ; }
set { state = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
Problem:
Whenever the page returns to the server and is reloaded, the state variable is always set to false or true depending on the initial state I passed, what I intended was for this variable to be loaded only once at the beginning of the page and then Could only be changed by codebeind.
I am grateful for your suggestions.
greetings
Patrick Veiga
You need to use the ViewState to store the property value to keep the persistent value saved.
public partial class WebUserControls_WUC_Tect : System.Web.UI.UserControl
{
private static bool state ;
public bool State
{
get
{
if (ViewState["MyState"] == null)
{
ViewState["MyState"] = false;
}
return (bool)ViewState["MyState"];
}
set
{
ViewState["MyState"] = value;
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
I want to ask you, what do you think, what is the best approach to get from second page to first page? I use something like this.(MVVM)
Second page:
public partial class AddProfilePageView : PhoneApplicationPage
{
public AddProfilePageView()
{
InitializeComponent();
DataContext = new AddProfileViewModel();
}
public AddProfileViewModel ViewModel { get { return DataContext as AddProfileViewModel; } }}
First page:
public partial class ProfilesPageView : PhoneApplicationPage
{
public ProfilesPageView()
{
InitializeComponent();
DataContext = new ProfilesViewModel();
}
public ProfilesViewModel ViewModel
{
get { return DataContext as ProfilesViewModel; }
}}
AddProfileViewModel() class has properties, that are binded to controls in xaml. From this page I need to get data to first page ProfilesPageView.
My solution is:
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
var content = e.Content as ProfilesPageView;
if (content != null && ViewModel.IsOk)
{
content.ViewModel.ProfilesList.Add(ViewModel.ProfileRecord);
}
}
So what do you think? Is it good solution how obtain data?
Thanks
In reality here you're not trying to get data from one page to another.
On the second/detail page you're adding a new item and then when you return to the first/main page you want it to update the displayed data to show the new item.
I'd assume that AddProfileViewModel and ProfilesViewModel are both persisting to disk/IsolatedStorage so you could just refresh the main/list/first page when returning to it.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
// ...
if (e.NavigationMode == NavigationMode.Back)
{
(this.DataContext as ProfilesViewModel).Refresh();
}
}
I'm developing an aplication for Windows 7, and I need to block a page.. my solutions are not register that frame or clear all the frames in back.
Guessing that you mean you have a page on the Back-stack that you want to remove --
In the new Mango SDK, there's a Method you can try NavigationService.RemoveBackEntry
However it might be easier to just use a boolean and check in OnNavigatedTo:
At page where you need to go back > 1 pages:
in App.xaml.cs:
public static bool IsBackwardNavigation = false;
public static string PageContext = string.Empty;
Page2.xaml.cs :
public void YourFunction()
{
App.PageContext = "MainPage";
App.IsBackwardNavigation = true;
if (NavigationService.CanGoBack)
NavigationService.GoBack();
}
And in each page's OnNavigatedTo:
Page1.xaml.cs:
string Page1 = "Page1";
protected override void OnNavigatedTo(object sender, NavigationEventArgs e)
{
if (App.IsBackwardNavigation)
{
if (!Page1.Equals(App.NavigationContext)
{
//since this page's name is not the correct page, the page will go back again.
if (NavigationService.CanGoBack)
NavigationService.GoBack();
}
else
{
//this is the page we're trying to get to
App.IsBackwardNavigation = false;
App.NavigationContext = string.Empty;
}
}
}
}
I've been reading other questions and pages and seen some ideas but could not understand them or get them to work properly.
My Example:
I have this checkBox1 on my mainpage.xaml
<CheckBox Content="Central WC / EC" Height="68" HorizontalAlignment="Left" Margin="106,206,0,0" Name="checkBox1" VerticalAlignment="Top" BorderThickness="0" />
I have a anotherpage.xaml with its c# on anotherpage.xaml.cs:
public void Feed(object Sender, DownloadStringCompletedEventArgs e)
{
if (checkBox1.Checked("SE" == (_item.Sector))) ;
{
}
}
How do I pass the value of the checkBox1 on the mainpage.xaml to the anotherpage.xaml.cs
You could pass whether the checkbox is checked when opening the next page:
NavigationService.Navigate(new Uri("/AnotherPage.xaml?chkd=" + checkBox1.IsChecked, UriKind.Relative));
You could then query this in the OnNavigatedTo event on the "other" page:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
string isChecked;
if (NavigationContext.QueryString.TryGetValue("chkd", out isChecked))
{
if (bool.Parse(isChecked))
{
//
}
}
}
Edit:
To pass multiple values just add them to the query string:
NavigationService.Navigate(new Uri("/AnotherPage.xaml?chk1=" + checkBox1.IsChecked + "&chk2=" + checkBox2.IsChecked, UriKind.Relative));
(You'll probably want to format the code a bit better though)
You can then get each parameter in turn from the
protected override void OnNavigatedTo(NavigationEventArgs e)
{
string is1Checked;
if (NavigationContext.QueryString.TryGetValue("chk1", out is1Checked))
{
if (bool.Parse(is1Checked))
{
//
}
}
string is2Checked;
if (NavigationContext.QueryString.TryGetValue("chk2", out is2Checked))
{
if (bool.Parse(is2Checked))
{
//
}
}
}
As you want to pass more and more values this will get messy with lots of duplicate code. Rather than pass multiple values individualy you could concatenate them all together:
var checks = string.Format("{0}|{1}", checkBox1.IsChecked, checkBox2.IsChecked);
NavigationService.Navigate(new Uri("/AnotherPage.xaml?chks=" + checks, UriKind.Relative));
You could then split the string and parse the parts individually.
You can declare a public property in the App class.
public partial class App : Application
{
public int Shared { set; get; }
//...
}
Then you can access it from the pages via:
(Application.Current as App).Shared
You could store a reference to the form or put an event or anything else you want to do.
On a side note, I highly recommend Petzold's WP7 book free for download.