I have a master detail page as the root page for my application. As a detail page for that I have a tabbed page. In the tabbed page I have a content page and a navigation page containing one content page. In the master detail's OnNavigatedTo I'm retrieving some organisation data from the cloud and then I want to navigate to a manage organisation page which is the plain content page in the tabbed page.
Using NavigateAsync and a relative uri to the manage organisation page I find that the Tabbed Page OnNavigatedTo is hit twice and then I get an exception such as (simplified) below. I can also see Binding errors in my output showing that elements on my manage organisation page xaml tried to bind to the tabbed page view model.
I'm not sure if this is an issue with the view model auto wire change in 6.2 or if it's a deep linking issue or if I've done something wrong.
"Sequence contains no elements".
at System.Linq.Enumerable.Last[TSource] (IEnumerable`1 source) [0x00079]
at Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer.OnAttachedToWindow () [0x00011]
in C:\BuildAgent\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\AppCompat\NavigationPageRenderer.cs:189
Using XF 2.3.1.114, Prism.Forms 6.2, I'm not sure if other packages are relevant. If you think so I can include them.
Also interestingly, it works if I try navigate to the content page in the navigation page from the master detail i.e. "TabbedPage/NavigationPage/ContentPage".
Any ideas what the problem might be?
So first thing first, you don't have the proper XAML syntax for your TabbedPage. When defining the default page for a NavigationPage in XAML you must supply the page via the Arguments element:
<views:SimpleNavPage Title="Foo">
<x:Arguments>
<views:NestedContentPage />
</x:Arguments>
</views:SimpleNavPage>
You must also have the proper ctor in your navigation page:
public SimpleNavPage(Page root) : base (root)
{
InitializeComponent();
}
Now, I personally don't recommend navigating within the OnNavigatedTo unless you can absolutely guarantee that you will not be adding that page in another deep link, or navigation scenario. Imagine you start out with NavigateAsync("MainPage") and that has an OnNavigatedTo that does a deep link navigation operation. Now you decide to NavigateAsync("SomeOtherPage") in which it NavigateAsyc("AnotherPage/MainPage/SomeOtherPage/LastPage") from within it's OnNavigatedTo. Now, you will have created an issue because the MainPage.OnNavigatedTO will have kicked off another navigation operation while you are still navigating to the next "SomeOtherPage". You are asking for trouble.
Related
I have some controls on a page in a Xamarin.Forms app that DO NOT WORK when navigating back to the page. I can only "go back" to the page by navigating to the page outright (I'm using Prism to do this) and it works.
When transitioning to MAUI, I'm writing my own navigation service to replace Prism. Everything works, except navigation to replace the first page and clear the navigation stack. This is NOT App.MainPage.Navigation.PopToRootAsync() The page is the first page in the navigation stack. Attempting to replace App.MainPage with a new page does not work. Nothing happens if I do this.
Example navigation stack:
MainPage
Page1
Page2
Navigation stack after navigating to new root page:
MainPage (but new instance of page, not the original instance). Remainder of navigation stack has been cleared.
I'm not sure what I was doing wrong, but further testing shows that you can replace MainPage for Maui.
You CANNOT just assign a NavigationPage to MainPage. This will work for the navigation and any logic in associated viewmodel will work, but the UI will be blank.
If you just assign a ContentPage to MainPage, everything works great.
Is it just me, or is it impossible to navigate to a page that does not have a .xaml head?
I am constructing a page entirely in code, and I want to navigate to it. I do not want a xaml page because this is a class library and also it is constructed based on data received. I know all about using .xaml to create the page with templates, binding, etc., but I want to avoid that.
When I call Frame.Navigate(typeof(CodePage)), I get nice AccessViolationException.
My page is simple, and so is the navigation. This is the code with a clean, new project
Navigation (button click):
Frame rootFrame = Window.Current.Content as Frame;
rootFrame.Navigate(typeof(CodePage));
Page:
public class CodePage : Page
{
public CodePage()
{
Content = new TextBlock
{
Text = "It works!",
};
}
I know about this issue: Navigate to a Page of another Class Library but, this is because ALL the pages are in the library, I just have 1 specific page in my library. Also, I have other pages in the "launcher" app.
Navigation only works with pages who have xaml part as well because when the page does InitializeComponent in its constructor it sets up the page for Navigation routes and NavigationCache etc.
Why we set master page in Page_Init event. We have other events in page.
For me one reason could be that master page does not have Pre_Init and other could be that Init of Page occurs before master page Init. Correct me if I'm wrong.
Master page is a UserControl. During Page.Init event, all the controls on the page are initialized(Control.Init is called). That's why the master page needs to be applied in Page.PreInit
Masterpage doesn't have PreInit method.
Master pages inherits:**System.Web.UI.MasterPage** and as per the design of this MasterPage class no such PreInit event is defined for this class.
Master pages are derived from Control class as seen in below hierarchy:
System.Object
System.Web.UI.Control
System.Web.UI.TemplateControl
System.Web.UI.UserControl
System.Web.UI.MasterPage
Therefore as can be guessed now, Master pages behave and in essence are treated like a control and have events similar to other asp.net server control
Because all things that 'dynamically' modify page controls have to occur there. This is where the page is rebuilt (form objects) with out request. Then things like page_load occur, after all objects are made.
Winforms analogy - if you are familiar with that - page_init is analogous to the InitializeComponent in the New (NOT REALLY SAME - just analogy please).
Only due to the nature of the web (at least round-tripping to the server), it can't possibly work like winforms (or WPF or even a SPA web app with a js/DOM UI and webapi backend) so has to rebuild the form's objects EVERY request.
Why does only the PAGE have page_init and not master page? Well as prateek says, but in addition, the rebuild of the page has to be control from just one spot. There is just one request. Controls can init, too as the page init process calls them in turn.
You have asked a question with a complicated answer.
Here is a good chart of what's going on...
http://www.codeproject.com/KB/aspnet/ASPDOTNETPageLifecycle.aspx
(source: codeproject.com)
Note how the postback data is loaded into the controls BEFORE the page_load, too - this is why it's too late to do anything big in the page load. You can't possibility get anything back from the user that was changed there (unless you go right to the postback data). The picture shows how ASP tries to 'fake' an event - driven UI on a client/server web architecture (e.g., 'event related logic' calls your 'events'). There is no such thing in client/server asp UI!
As a master page is the default screen throught the application ,it should be initialized first before the child pages.In order to get initalized earlier it is done in pre_init where the master page is loaded.later in Init() all the child pages are loaded regarding to that master page.
During the ASP.NET page life cycle, the initialization is also included on the master page. This is where the design and all the controls that are on the master page will be available before the page is loaded, which will be the "Load" phase of the page life cycle. If the master page is not initialize, you would get a page with no design, except the information on the page.
"During page initialization, controls on the page are available and each control's UniqueID property is set. A master page and themes are also applied to the page if applicable. If the current request is a postback, the postback data has not yet been loaded and control property values have not been restored to the values from view state."
https://msdn.microsoft.com/en-us/library/ms178472.aspx
I have a ASP.Net MVC view which contains other partial views derived of ViewUserControl. The view itself is contained in a master page, so the control hierarchy can be summarized as follows:
Master page - basic settings
ViewPage - "the" page
ViewUserControl - content component 1
ViewUserControl - content component 2
...
ViewUserControl - content component n
Additionally, we have a custom control for the declaration of CSS and Javascript files. This custom control ensures that, no matter how deep into the hierarchy, whenever there is a CSS or JS dependency it will be rendered inside the Page.Header, thus avoiding scattered and duplicated references. Let's call this custom control <my:dependency>.
All is well when <my:dependency> is hosted in the master or ViewPage. But if I use it deeper inside the content components, Page.Header is null. Debugging revealed that, for controls hosted in a ViewUserControl, their Page is the very ViewUserControl in which they're in, and so the Header is indeed missing.
How can I make <my:dependency> "see" the topmost ViewPage and get access to the Header? Thanks.
Now I could be wrong, but you appear to be trying to get a web forms control to work in MVC, something that is not recommended for reasons you've discovered.
You might want to look at something involving the ViewData collection.
Simon
From what I've already read this appears to be impossible, but I wanted to see if anyone out there has a secret trick up their sleeve or at least a definitive "no".
Supposedly a master page is really just a control for a content page to use, not actually the "master" of a content page. If I wanted to go from one content page, to another content page with the same master page, I would just say
Response.Redirect("PageB.aspx");
But this would immediately cause a postback, flickering the page, which is the crappy pre-ajax way of doing things.
In this current project, I'm trying to see if I could figure out how to change the current content page of a ContentPlaceHolder in the master page asynchronously, when a button is clicked on the master page.
Is this possible, if so how?
I don't know if you can between pages (.aspx) but it can definitely be done using UserControls.
ASP.Net pages each have their own URL so what you're trying to do is to go from one URL to another without any postback, that's just not how it's supposed to work.
Using user controls (.ascx):
Create a page that uses the MasterPage and use something like this in the content
<ajax:UpdatePanel ...>
<ContentTemplate>
<asp:PlaceHolder ...>
</ContentTemplate>
</ajax:UpdatePanel>
Search for UpdatePanel and tweak its settings to do what you want, then learn how to swap user controls in a placeholder.
No, you cannot because a master page is actually a control rendered on a particular aspx page, rather than actually containing the aspx page as it deceptively appears to be programmatically and in design view.
More Info:
You could however use a variety of other controls to simulate this effect. The asp:MultiView control is one example, each "page" could be made in a single view and placed in an update panel, thus allowing it to be switched asynchronously. Alternatively you could define each page in a separate user control and put those in an update panel, asynchronously switching the visible property on those controls as needed.
There are really a lot of different ways to achieve an effect similar to changing the master page's content placeholder.