my current navigation stack has two pages. First is page A, second is Page B. When I click my button, It'll add a new page to the navigation stack, Page C.
May I ask how do I display Page C and remove Page B, or remove page B and display page C.
I've tried the following
await Navigation.PopAsync()
await Navigation.PushAsync(new CustomPage())
The issue i'm having with this is that the page pops successfully, but the new page isn't visible. I immediately see page A. May I ask how do I pop the current page and immediately show another.
Instead of popping the page and then trying to push the new page. I would push your new page then remove the previous page from the NavigationStack.
var previousPage = Navigation.NavigationStack.LastOrDefault();
await Navigation.PushAsync(new CustomPage());
Navigation.RemovePage(previousPage);
You can also Remove every Page from the NavigationStack in the OnAppearing Method from the next Page. In this example the first Page...
protected override void OnAppearing()
{
// Remove LoginPage from NavigationStack
if (Navigation.NavigationStack.Count > 1)
{
Page page = Navigation.NavigationStack.First();
if (page != null && page != this)
{
Navigation.RemovePage(page);
}
}
base.OnAppearing();
}
Related
I have a MasterDetailPage. I can add a page from my "Menu" and it is content inside the master page. When I want to do the same but with a button from my "FirstMasterPage" it show the Page but over the MasterDetailPage
I tried to create a new MasterPage but not showing nothing
This is the action of the button of one of my pages
Navigation.PushModalAsync(new Pagina_Dos());
I also tried this, but showing nothing. Pagina_Master is my MasterDetailPage
MasterDetailPage mdp = new Pagina_Master();
mdp.Detail.Navigation.PushModalAsync(new Pagina_Dos());
mdp.IsPresented = false;
I want to show my content Page (Pagina_Dos) inside my Master Detail Page, when is clicked from the button. Because from the menu of course its working
first you need a reference to the current MasterDetailPage
var mdp = (MasterDetailPage)App.Current.MainPage;
then you can use the Detail's Navigation property to push a new page
mdp.Detail.Navigation.PushAsync(new Pagina_Dos());
I'm new with Xamarin.Forms, and I'd like to know how to switch to a "previously loaded" Page.
Let say my App run, and it loads (as First Page) my MainPage. There I tweak some button/toggle (changing status), and than I click on a button that will load another Page (using Navigation model):
await Navigation.PushAsync(new MyNewPage());
Now here I want to return to the previous MainPage
await Navigation.PushAsync(new MainPage());
But at this point, all content/button status are vanished (basically it creates a new MainPage).
Since its a LIFO, I aspect to have it on memory/stack. How can I recall the previous loaded MainPage? Or is it dangerous since GC could clean it at any point?
Notice that in this specific case this would works (since I just back one time):
await Navigation.PopAsync();
But I'd like to use a selective approch (calling what I need where I am, learning the whole concept).
One thing to note is that the Navigation object you use to Push and Pop has a NavigationStack property you can use to get previously pushed pages - assuming you didn't pop them.
To the best of my knowledge, there aren't any methods to directly navigate to an existing Page in the stack so you may have to get somewhat creative in your approach.
If MainPage is always at the bottom of your NavigationStack, you can use
await Navigation.PopToRootAsync()
to go back to the Page at the bottom of the stack.
If 'MainPage' can be elsewhere in the stack, you may have to maintain your own list of Pages separate from the NavigationStack.
Something like the following may work if you don't care about keeping the Pages between MainPage and your current page:
Note that you will want to create a separate List of Pages to remove as calling RemovePage() on the NavigationStack in the foreach loop will cause an exception sometimes, something to the effect of "Enumeration can't complete, collection has changed":
List<Page> pagesToRemove = new List<Page>();
foreach( Page page in Navigation.NavigationStack )
{
if( page.GetType() != typeof(MainPage) && page != Navigation.NavigationStack.Last() )
{
pagesToRemove.Add(page);
}
}
// pagesToRemove now contains all Pages between your current page and MainPage
foreach( Page pageToRemove in pagesToRemove )
{
Navigation.RemovePage(pageToRemove);
}
// the NavigationStack only contains MainPage (now the root) and your current page
// Pop to MainPage
await Navigation.PopAsync();
Someday it would be nice to have a NavigateTo(Page) or the like but for now this approach seems to work.
I need to go back to a particular page when I click on a button. more like custom back button.
I can go exact page, if I know what is the page is,
private void button_click(object sender, RoutedEventArgs e)
{
Frame.Navigate(typeof(Page1));
}
Also I can go back to the previous page by
if(this.Frame.CanGoBack)
{
Frame.GoBack();
}
But how can I jump to the page before the previous page at once?
Any record of page history?
You can use NavigationServices.BackStack to access on an history of your previous pages.
But you have not specific method to go back from 2 pages at once. However, if you would jump to the page before the previous page you have just to called NavigationServices.GoBack() two times.
Moreover, if you would go back to a specific page, you can know its index between backstack and make a loop with the GoBack method.
You can get all pages from BackStack as a List :
var lstAllStackPages = this.Frame.BackStack.ToList();
and make a for loop to get your specific page and navigate to it.
Thank you #CoderDennis, I figured it out. hope it will help to someone else.
I wanted to move back to the Main page if I have come along the Main page,
foreach (PageStackEntry stack in Frame.BackStack)
{
//check if stack contains history of the main page. (Solution name: Helloworld)
if (stack.SourcePageType == typeof(HelloWorld.MainPage))
{
Frame.Navigate(stack.SourcePageType);
break;
}
}
Here is the sequence in which events occur when a master page is merged with a content page:
http://msdn.microsoft.com/en-us/library/dct97kc3.aspx
So, my problem is:
I have one login page (not use master page), one master page, and hundreds of content page.
I check login session Session["loggedInUser"] in master page (if not logged in, redirect to login page)
So, when I don't log in, if I type the address of one content page, it must check login session in master page and redirect to login page, right? But it has two cases here:
If in content page, I don't use anything related to Session["loggedInUser"], it will redirect to login page, so, it's OK here!
The second case: if I use Session["loggedInUser"] to display Username in content page for example:
UserInfo loggedInUser = (UserInfo)Session["loggedInUser"];
it will return null object here, because the page_load in content page is fired before page_load in master page, so it thows null object instead of redirecting to login page.
I also tried Page_PreInit in master page but no help
protected void Page_PreInit(object sender, EventArgs e)
{
if (Session["loggedInUser"] == null)
{
Response.Redirect("~/Login.aspx");
}
}
Any suggestion?
Presumably, when you say you are using the Session["loggedInUser"] value, you are then calling .ToString() method or similar to display it?
In which case, you will need to check for a null object before using it. It would be best practice to check for the existance of the object before using any methods on it in any case, so:
if (Session["loggedInUser"] != null)
{ ... }
Only if you are certain that the code will never be executed without the Session object being instantiated can you use methods without checking for a null reference.
http://msdn.microsoft.com/en-us/library/03sekbw5.aspx
Finally I've come up with a solution:
I create a class BasePage like this:
public class BasePage : System.Web.UI.Page
{
protected override void OnLoad(EventArgs e)
{
if (Session["loggedInUser"] == null)
{
Response.Redirect("~/Login.aspx");
}
base.OnLoad(e);
}
}
And in the content page, instead of inheriting from Page, I change to BasePage and it works perfectly
Thanks for all of your support
Nice day ;)
You could check for Session["loggedInUser"] in the content Page's Page_PreRender() rather than Page_Load()or alternatively, do the master page check in the Page_Init() rather than Page_Load(). We had the same problem and went with the Master page Page_Init() option, so that we could still use Page_Load() in all the Content pages.
Edit: It's Page_Init() not PreInit().
I have 2 masterpages(1 for prelogin,2nd for afterlogin),home page is independent,logout page inherits postlogin page) in all postloginpage session chck if sessionnull(xyz)else(redirect loginpage) all this in Page_Init event of afterlogin.master................Successfull
There are two scenarios for an ASP.net webforms page which I would like to differentiate between: "Normal postback" and when a page is created because the next page has called PreviousPage.
A normal posback occured for page 1
IsPostback is true
IsCrossPagePostBack is false
and
There was a Server.Transfer("page2.aspx") to page 2, and page 2 uses PreviousPage so page 1 is created virtually. For page 1:
IsPostback is true
IsCrossPagePostBack is false
You can see that IsPostBack and IsCrossPagePostBack do not help because they are the same in both cases.
The reason why I am asking this:
I have page 1 which sends data to page 2 via cross-page postback (PostBackUrl="page2.aspx" set in page 1). For all users who have javascript enabled, this works fine.
But I wanted also a fallback for the users who have javascript disabled. For them, a click on the submit button on page 1 does not lead to page 2 but to a postback to page 1. Page 1 could now detect this and do a Server.Transfer("page2.aspx") to page 2. The problem is: When page 2 uses PreviousPage then page 1 is created again and would do a Server.Transfer() again and again and again ...
My workaround for this is to do the Server.Transfer not in the Page_Load event but only in the Page_PreRender event because this event does only occur when it is a normal postback and not when the page is created as PreviousPage.
This workaround works but it is very dirty. If I could differentiate between the two scenarios already in the Page_Load event, it would be much better.
Is this possible?
When you do the HttpServerUtility.Transfer from Page 1 to Page 2, the HttpContext is then shared between Page 1 and Page 2. So normally, one request means one request handler (usually a page) and one request context. But in this case there's two handlers and one (shared) context. You can use the context to share information about the request between the two handlers.
So one solution may be that Page 1 puts all the data that page 2 needs in the HttpContext.Items. Then Page 2 first checks for this data. If present, Page 2 knows that control was transferred by way of Server.Transfer and that it should not call on Page 1 through PreviousPage. Instead it should now get its data from the context.
Page1.aspx
protected void Page_Load(object sender, EventArgs e)
{
if(IsPostBack && HttpContext.Items.Contains("CrossPagePostBack") == false)
{
// Cross page postback did not succeed (JavaScript disabled)
string name = NameTextBox.Text;
HttpContext.Items.Add("Name", name);
HttpContext.Items.Add("Transfer", true);
Server.Transfer("Page2.aspx");
}
}
Page2.aspx
protected void Page_Load()
{
if(IsPostBack)
{
string name;
if(CrossPagePostBack)
{
// Cross page postback succeeded (JavaScript was enabled)
HttpContext.Items.Add("CrossPagePostBack", true);
name = PreviousPage.NameTextBox.Text;
}
else if (HttpContext.Items.Contains("Transfer"))
{
// We got transferred to from Page1.aspx
name = (string)HttpContext.Items["Name"];
}
// Do something with Page 1's form value(s)
}
}
Or you can turn this around and let Page 2 add a mark ("Page 2 was here") to the HttpContext.Items, and then Page 1 checks that mark. If it's present it doesn't need to transfer again (break the loop). I'm not 100% sure if a call to PreviousPage also results in a shared request context.
Page1.aspx
protected void Page_Load(object sender, EventArgs e)
{
if(IsPostBack && HttpContext.Items.Contains("CrossPagePostBack") == false)
{
// Cross page postback did not succeed (JavaScript disabled)
if(HttpContext.Items.Contains("Transfer"))
{
// We did not yet transfer to Page 2
HttpContext.Items.Add("Transfer", true);
Server.Transfer("Page2.aspx");
}
}
}
Page2.aspx
protected void Page_Load()
{
if(IsPostBack)
{
if(CrossPagePostback)
{
// Cross page postback succeeded (JavaScript enabled)
HttpContext.Items.Add("CrossPagePostBack", true);
}
string name = PreviousPage.NameTextBox.Text;
// Do something with Page 1's form value(s)
}
}
The second method is simpler in implementation, especially if the form on Page 1 is complex. You'd have only one place where you read Page 1's form, and you only add a simple boolean to the HttpContext.Items.