In a windows phone app,a page is navigated to another page and on pressing back button, goes back to previous page.Now in previous page the previous data has to be displayed. But its not displaying immediately and takes some time to load. How to solve this issue?
Overall the question is how to maintain the content of page(containing dynamic data) displayed in back navigation?
Use PhoneApplicationService class to keep the data while you navigate between the pages. Here is some samples. Actually, it's very easy:
protected override void OnNavigatedFrom(NavigationEventArgs args)
{
if (ContentPanel.Background is SolidColorBrush)
{
Color clr = (ContentPanel.Background as SolidColorBrush).Color;
if (args.Content is MainPage) (args.Content as MainPage).ReturnedColor = clr;
// save color
PhoneApplicationService.Current.State["Color"] = clr;
}
base.OnNavigatedFrom(args);
}
protected override void OnNavigatedTo(NavigationEventArgs args)
{
// restore color
if (PhoneApplicationService.Current.State.ContainsKey("Color"))
{
Color clr = (Color)PhoneApplicationService.Current.State["Color"];
ContentPanel.Background = new SolidColorBrush(clr);
}
base.OnNavigatedTo(args);
}
How to preserve and restore page state for Windows Phone
You can use single ton object of View Model to store data in a page provided all the controls are bind to a property in View Model.
Then if you do not clear the values of the controls when navigating away from the page, the data will be displayed in the page when you navigate back to that screen provided all the controls
Related
I've got this code for creating a WebView:
public class SessionsActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.discover);
//declare webview and tell our code where to find the XAML resource
WebView discoverWebView = FindViewById<WebView>(Resource.Id.webViewDiscover);
//set the webview client
discoverWebView.SetWebViewClient(new WebViewClient());
//load the subscription url
discoverWebView.LoadUrl("https://www.bitchute.com/");
//enable javascript in our webview
discoverWebView.Settings.JavaScriptEnabled = true;
//zoom control on? This should perhaps be disabled for consistency?
//we will leave it on for now
discoverWebView.Settings.BuiltInZoomControls = true;
discoverWebView.Settings.SetSupportZoom(true);
//scrollbarsdisabled
// subWebView.ScrollBarStyle = ScrollbarStyles.OutsideOverlay;
discoverWebView.ScrollbarFadingEnabled = false;
}
}
but when I click on links inside my app, the page loads at the same spot as the last page was, which makes navigation very difficult, because mobile pages are supposed to load from the top, not from the middle. So basically, if I am in my subscriptions feed, and then I scroll down to find more content, I click on a user, and their video page loads videos from weeks ago, because it loaded with the same view elevation as the root page.
The site I'm using WebView with is also designed for mobile users, if that matters. The weird thing is that this used to not happen until recently... don't know what changed. How can I have the WebView load at top of page on each click?
I'm using TabHost for this .. here's my full code for context
https://github.com/hexag0d/BitChute_Mobile_Android_a2/blob/2.68/MainActivity.cs
thanks in advance!
I have 2 pages in my Xamarin Forms app. My first page has 4 icons in the toolbar. My second page is a login page and has a tick and a cross in the toolbar.
I can't get the login page to show any icons unless I make it a navigation page. I also have to clear ToolBarItems on the first page before calling PushAsync() otherwise it complains there are too many toolbar items.
If I call PopAsync() on the login page it does not return to the first page. I'm guessing this is due to their being 2 navigation pages. I also tried PopToRootAsync().The back button works however.
My question is - how do I show different toolbar icons on 2 different pages in a way that allows navigation to work?
I'm testing this on Windows Phone 8.0
Here is the code calling the login page:
private async void ShowLoginPage()
{
ToolbarItems.Clear();
var page = new NavigationPage(new LoginPage());
await Navigation.PushAsync(page);
}
and here is the code to return to the first page:
private void Cancel()
{
Navigation.PopToRootAsync();
}
I'm running Xamarin.Forms v1.2.2.6243
One thing you could try is to keep your Login Page inside of a NavigationPage, and then instead of running PopAsync() within the Login Page after they have logged in successfully, simply replace the MainPage with your old Navigation page:
In your App class:
public NavigationPage AppNavPage = new NavigationPage(new FirstPage());
public App() {
MainPage = AppNavPage;
}
In your FirstPage:
private async void ShowLoginPage() {
ToolbarItems.Clear();
var page = new NavigationPage(new LoginPage());
await Navigation.PushAsync(page);
}
In Login Page:
private async void OnCreateClicked(object sender, EventArgs e) {
bool loginInfoIsGood = CheckLoginInfo(); //Check their login info
if(loginInfoIsGood) {
Application.Current.MainPage = App.AppNavPage;
}
}
Otherwise, I have also done a custom renderer for the NavigationRenderer on iOS to insert toolbar items onto the right side of the Navigation Bar and have overridden some Menu related stuff on Android to change the icon text/colors.
One option that you have, and one that I implemented in my own app, is a custom renderer that removes the navigation header from the app and then you could build your own custom header. With this approach, you do lose some of the native feel of the app, and you have to implement much of the transitional functionality your self. However, it gives you alot more control over the look.
CustomRenderer that removes the navigationBar:
//add using statements
// add all view here that need this custom header, might be able to build a
//base page that others inherit from, so that this will work on all pages.
[assembly: ExportRenderer(typeof(yourView), typeof(HeaderRenderer))]
class HeaderRenderer : PageRenderer
{
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
this.NavigationController.SetNavigationBarHidden(true, true);
}
}
After this you can build a header view that can be placed on the top of every page (I am using xaml) so I don't know if it is relevant in you application.
Edit: You might need to change this renderer for differnt page types.
I have above scenario: If user click on ListBox, it will either have sub items (again ListBox) or detail view.
So what i did currently is: Whenever user clicks any item, made a web call and filled up the same ListBox if clicked item is having further sub items.
Now, issue comes in picture:
Suppose i am in 4th screen (detail view),
Moved to the 3rd and 2nd screen with data maintained as stack (Its working fine, yes i am maintaining data in ObservableCollection<ObservableCollection<MyObjects>> so while moving back, i am fetching data from there)
Now, if i click any item in screen 2, it will open detail view for the screen 3 ListBox data.
Means that ListBox is not getting notified that we have filled data inside OnBackKeyPress()
FYI, i am filling up ListBox and WebBrowser in the same page., so my problem is that how do i notify ListBox once i filled up data from stack which i have maintained?
Yes i have also implemented INotifyPropertyChanged but don't know why its not working.
Please check my code:
ListBox and WebView screen: http://pastebin.com/K1G27Yji
RootPageItem class file with the implementation of INotifyPropertyChanged: http://pastebin.com/E0uqLtVG
sorry for pasting code in above way, i did as question is being long.
Problem:
How do i notify ListBox that data is changed from OnBackKeyPress?
And what is the behavior if you set:
listBox1.ItemsSource = null;
before
listBox1.ItemsSource = listRootPageItems;
This is just wrong architecture. Instead of reloading the same listbox, please add a single page for each screen. Share data between them inside the App class (internal static) and use the built in navigation stack for handling "going back". Don't override OnBackKeyPress for this purpose.
You will get your desired functionality for "free" with easier to maintain and use codebase.
Oops it was a silly mistake i made.
I forgot to set items[] array inside OnBackKeyPress() but was accessing while clicking item, hence its having items[] data of last step we moved in forward direction, it was executing the same data.
Now, i have just included a single line and it has solved my problem.
items = listRootPageItems.ToArray(); // resolution point
So final code of onBackKeyPress() is:
/**
* While moving back, taking data from stack and displayed inside the same ListBox
* */
protected override void OnBackKeyPress(CancelEventArgs e)
{
listBox1.Visibility = Visibility.Visible;
webBrowser1.Visibility = Visibility.Collapsed;
listBox1.SelectedIndex = -1;
if (dataStack.Count != 0)
{
listBox1.ItemsSource = null;
listRootPageItems = dataStack[dataStack.Count-1];
listBox1.ItemsSource = listRootPageItems;
items = listRootPageItems.ToArray(); // resolution point
dataStack.Remove(listRootPageItems);
e.Cancel = true;
}
}
I have an app in which I have a lot of references and the load time was not acceptable to me. I have removed the splash screen image and created an animated loading screen by having a separate project with no reference to the main application which then navigates to the first page of the rest of the app. It does start up fast now but it's a little lacking still.
I would like to do another animation right before the load screen goes away. The only way I can think of to do this is to actually preload the assemblies needed for the navigation to the next page, do an animation, and then navigate.
I have tried
OnNavigatedFrom but the animation doesn't have time to run since the page will be replaced by the new page very quickly from that point.
OnNavigatingFrom is no help either as it is called as soon as I call NavigationService.Navigate();
Searching the web and Stack Overflow :)
I also considered faking it a bit by having the next page show a duplicate of the load screen and do the last animation there, but it can't match the current state of the load screen animation and is harder to maintain
Thanks for any ideas!
If you want to force the loading of an assembly, just reference a type from this assembly.
For instance, something like Console.WriteLine(typeof(YourAssembly.SomeType)); will force the loading of YourAssembly.
Now for your problem, maybe you can use usercontrols? Put the content of your main page in a user control. Display the loading page, create the usercontrol in the background, let the animation play, then when the animation is done playing replace the page's content with the usercontrol.
It turns out that you can preload by just creating a new instance of the page you are going to navigate to. Unfortunately that has to be done on the UI thread which can cause animation slowdown, at least in my experience.
Here is a sample of how to do an animation, then preload, then do another animation before navigating. :
public partial class LoadScreen : PhoneApplicationPage
{
public LoadScreen()
{
InitializeComponent();
this.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
var sb = new Storyboard();
// create your animation here
sb.Completed += (sender, args) => PreLoad();
sb.Begin();
}
private void PreLoad()
{
// this is the part that actually takes time and causes things to get loaded
// you may need it in a try/catch block depending on what is in your constructor
var page = new PageToNavigateTo();
// now create an animation at the end of which we navigate away
var sbOut = new Storyboard();
// create your animation here
sbOut.Completed += (sender, args) => NavigateToNextScreen();
sbOut.Begin();
}
private void NavigateToNextScreen()
{
// navigate here
}
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
// remove the loading screen from the backstack so the user doesn't see it again when hitting the back button
NavigationService.RemoveBackEntry();
}
}
I have an application, the main page contains few functions. To explain in detail - I have save, color palette button in my main page. When any of these buttons are clicked, save pop up or color palette appears. How to handle back button of the device, when color palette or save pop up is opened. When back button is pressed at these scenario it should just make them invisible and stay on the main page. When nothing is being performed in the main page, then it should come out of the app. I tried to make their visibility collapsed on back button press. But it still is coming out of the application.
Please, guide me in this. Thanks in advance.
Override PhoneApplicationPage.OnBackKeyPress and then set CancelEventArgs.Cancel to true if you want to stop it from actually going back.
protected override void OnBackKeyPress(CancelEventArgs args)
{
if (PanelIsShowing)
{
HidePanel();
args.Cancel = true;
}
}
The back button behaves as is intended by Microsoft.
If you change its behavior you risk your application not being certified for the Marketplace.
If you want the back button to close the popups, turn the popups into pages so the back button navigates back to the main page..
You need to use
protected override void OnBackKeyPress(CancelEventArgs e)
{
if (_popup.IsOpen)
{
_popup.IsOpen= false;
e.Cancel = true;
}
else
{
base.OnBackKeyPress(e);
}
}
That should do the trick.