Windows Phone 8.1 - Page Navigation - c#

Coming from Windows Phone 8 I have never thought there will be a lot of changes done to the Windows Phone 8.1 code. Basically I'm just wondering how to do page navigation just like how you would do it on Windows Phone 8. To do that you should add:
NavigationService.Navigate(new Uri("/SecondPage.xaml", UriKind.Relative));
but that code doesn't work for Windows Phone 8.1.
Can someone please help me with this? If possible provide any links or documentation on all the new Windows Phone 8.1 methods.

In Windows Phone 8.1, Page Navigation method is like this:
Frame.Navigate(typeof(SecondPage), param);
It means that you will navagate to 'SecondPage', and pass 'param' (a class based on object).
If you needn't to pass any parameters, You can use this:
Frame.Navigate(typeof(SecondPage));
You can find the documentation for this MSDN link

In case you want to go back you can use:
if(this.Frame.CanGoBack)
{
this.Frame.GoBack();
}
If you want to go back on the click of back button, you need to override the hardwarebutton event:
HardwareButtons.BackPressed += HardwareButtons_BackPressed;
void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if(rootFrame != null && rootFrame.CanGoBack)
{
rootFrame.GoBack();
e.Handled = true;
}
}
Make sure to set e.Handled to true.

// Navigation Without parameters
this.Frame.Navigate(typeof(SecondPage));
// Navigation with parameters
this.Frame.Navigate(typeof(SecondPage),MyParameters);

To send multiple parameters:
Its quite late to answer but might help someone. You can create a custom class, set your parameters in it and send its object as a parameter to your target page.
For example. Your custom class:
public class CustomDataClass
{
public string name;
public string email;
}
CustomDataClass myData = new CustomDataClass();
myData.name = "abc";
myData.email = "abc#hotmail.com";
Frame.Navigate(typeof(SecondPage), myData);
And then on the target page you can retrieve in OnNavigatedTo function like this:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
CustomDataClass myData2 = e.Parameter as CustomDataClass;
string name = myData2.name;
string email = myData2.email;
}
Hope it helps.

Related

Windows Phone 8.1: Save list in app settings/storage

I just started developing a Windows Phone 8.1 app.
The app allows the user to add 'data' (strings) to his favorites-list.
Now the question is:
What is the best way to save the list or the single entries of the list so I am able load these favorites again on the next app start?
I thought I should save the data to a (text-) file so I can read it line by line and put the list together again.
What do you think, is this the best way to handle something like this? I am new to the Windows Phone 8.1 platform and any help is really appreciated - thanks!
The best method depends on size of data and your needs. As for saving it in Settings you can try to make an array of string upon save and make list upon loading data. Simple example can look like this:
List<string> favourites = new List<string>();
protected void Method()
{
// save as array
ApplicationData.Current.LocalSettings.Values["myList"] = favourites.ToArray();
// retrive your array and make a list from it
favourites = ((string[])ApplicationData.Current.LocalSettings.Values["myList"]).ToList();
}
Remember that LocalSettings support only simple types and have other limits - for more information take a look at MSDN.
I think i finally got it to work. Should thought about something like that much earlier.
So I got my async Task SaveAppSettingsAsync() and just call it in the Suspending-Event and in my Hardwarebuttons_Pressed-Event when the app closes:
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
await SaveAppSettingsAsync();
deferral.Complete();
}
private async void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame != null)
{
e.Handled = true;
if (rootFrame.CurrentSourcePageType == typeof(MainPage))
{
await SaveAppSettingsAsync();
this.Exit();
}
else if (rootFrame.CanGoBack)
rootFrame.GoBack();
}
}
Thanks for helping. I think I got better at understanding how to handle async tasks now. As I said - I'm new to Windows Phone and never really used them before.

Don't have OnActivated method in app.xaml.cs Windows Phone 8.1

I'm actually working on an application which was a blank Windows Phone app 8.1 at the beginning. I wanted to implement the app with a FileOpenPicker to get a picture from the device. In WP 8.1, I have to use PickSingleFileAndContinue method of the OpenFilePicker. So I've read about configuring my project to handle Continue event here: your Windows Phone Store app after calling an AndContinue method MSDN. One of the steps is to implement the OnActivated method in the app.xaml.cs file.But there is no OnActivated method in my app.xaml.cs.
I've copy paste that method from the above link but the MainPage object used in that method doesn't have a Current state:
protected async override void OnActivated(IActivatedEventArgs e)
{
base.OnActivated(e);
continuationManager = new ContinuationManager();
Frame rootFrame = CreateRootFrame();
await RestoreStatusAsync(e.PreviousExecutionState);
if (rootFrame.Content == null)
{
rootFrame.Navigate(typeof(MainPage));
}
var continuationEventArgs = e as IContinuationActivatedEventArgs;
if (continuationEventArgs != null)
{
Frame scenarioFrame = MainPage.Current.FindName("ScenarioFrame") as Frame;
if (scenarioFrame != null)
{
// Call ContinuationManager to handle continuation activation
continuationManager.Continue(continuationEventArgs, scenarioFrame);
}
}
Window.Current.Activate();
}
As I'm knew to Windows Phone and just facing the states management of an app, I cannot really figure out where that error comes from. Maybe someone got an idea ?
It won't be 100% clear until you download the full source code example off that link. They neglected to post the full example (too much code). Download the C# demo project and look at it.
MSDN FilePicker FULL SOURCE
public sealed partial class MainPage : Page
{
public static MainPage Current;
public MainPage()
{
this.InitializeComponent();
// This is a static public property that allows downstream pages to get a handle to the MainPage instance
// in order to call methods that are in this class.
Current = this;
Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed;
}
}
As you can see it's just a static declaration.

Frame.Navigate in LoadState

I'm having trouble trying to navigate automatically between pages in my Windows 8.1 app based on a little check. It just doesn't want to navigate to another page when doing this in LoadState, as if something isn't loaded yet, but it doesn't give an error either. When I insert a delay using (for example) await Task.Delay(2000) before doing Frame.Navigate, then my app will redirect without any problem.
protected async override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
MyData oData = await getData();
if (oData != null)
{
this.Frame.Navigate(typeof(newPage), oData);
}
else
{
// do something else
}
}
Do I have to put this code in another load- or navigated-event? Or how can I make this work?
In LoadState and SaveState you should only save and restore the page state (called when suspending and reactivating the app). Do nothing else (like navigating).
Put your logic into the OnNavigatedTo method instead...
If you want to navigate from method that called when page is loads, you should place your navigation code to OnNavigatedTo(...). But do not forget to wrap your code in Dispatcher.RunAsync(...) - Frame navigation in xaml return false
I tried calling Frame.Navigate(...) from the OnNavigatedTo method but still the navigation didn't occur.
There are other answers which say use Dispatcher.RunAsync, but that feels like it's making assumptions about the threading model of Windows Phone.
Here's what I do: attach a handler to the Loaded event of the page instead, and put my "redirect" logic in there. Loaded fires after OnNavigateTo and after NavigationHelper_LoadState, but before the page has become visible.
public LaunchPadPage() {
this.InitializeComponent();
this.navigationHelper = new NavigationHelper(this);
this.navigationHelper.LoadState += this.NavigationHelper_LoadState;
this.navigationHelper.SaveState += this.NavigationHelper_SaveState;
this.Loaded += LaunchPadPage_Loaded;
this.app = (App)App.Current;
}
private void NavigationHelper_LoadState(object sender, LoadStateEventArgs e) {
// Let's show the root zone items
// NB: In case we don't have this data yet, do nothing
if (app.Hierarchy != null)
{
DefaultViewModel["Items"] = app.Hierarchy.RootItems;
}
}
private void LaunchPadPage_Loaded(object sender, RoutedEventArgs e) {
// No data? Go to the downloads page instead.
if (app.Hierarchy == null)
{
Frame.Navigate(typeof(DownloadingPage));
}
}

Change DefaultTask if some settings already exist

In Windows phone 8 app, instead of always opening the application with same PhoneApplicationPage, I need to switch the initial view. i.e. Home page if settings already exists and settings page if the user opens the app for the first time.
How should I go about it?
Currently the way I adopted is :
Made Default task empty in WMAppManifest.xml
<DefaultTask Name="_default" />
Decided which page to move to in Application_Launching event handler.
private void Application_Launching(object sender, LaunchingEventArgs e)
{
if (SettingFileExists())
RootFrame.Navigate(new Uri("Home.xaml", UriKind.Relative));
else
RootFrame.Navigate(new Uri("Settings.xaml", UriKind.Relative));
}
Is this the best way to approach this scenario? Is there any potential issue with my code?
There a re lots of different ways of doing this and no one "best" way.
My personal preference is to use a custom UriMapper that does the redirect on start up.
E.g.
Set the Navigation startup Uri to something special that doesn't exist. e.g. "StartUp"
Set a custom UriMapper:
RootFrame.UriMapper = new MyUriMapper();
Then in the UriMapper check for the special uri and take appropriate action:
public class MyUriMapper : UriMapperBase
{
public override Uri MapUri(Uri uri)
{
if (uri.OriginalString == "/StartUp")
{
if (!this.dataOperations.IsLoggedIn())
{
return Login.Path;
}
else
{
return Main.Path;
}
}
return uri;
}
}

Remove / hide the Bing map offline message when offline

I'm developing a Windows Phone app that uses the older WP7 Microsoft.Phone.Controls.Maps.Map / Bing Map control.
The map tiles are being served up from a local source so the app doesn't not need a network connection to work. Unfortunately the map control insists on showing an "Unable to contact Server. Please try again later." message over the map when offline.
Does anyone know of a method to remove / hide this message?
Just in case you're curious - I'm developing a WP8 app but using the depreciated WP7 Bing map control as the new WP8 map control provides no method for replacing the Bing base map.
i think this may suits you better:
void YourPage_Loaded(object sender, RoutedEventArgs e)
{
m_Map.ZoomLevel = 11;
m_Map.LayoutUpdated += m_Map_LayoutUpdated;
}
void m_Map_LayoutUpdated(object sender, EventArgs e)
{
if (!isRemoved)
{
RemoveOverlayTextBlock();
}
}
void RemoveOverlayTextBlock()
{
var textBlock = m_Map.DescendantsAndSelf.OfType<TextBlock>()
.SingleOrDefault(d => d.Text.Contains("Invalid Credentials") ||
d.Text.Contains("Unable to contact Server"));
if (textBlock != null)
{
var parentBorder = textBlock.Parent as Border;
if (parentBorder != null)
{
parentBorder.Visibility = Visibility.Collapsed;
}
isRemoved = true;
}
}
You have to include a class LinqToVisualTree witch can be downloaded from here.
And here is the original post
You can either handle the LoadingError event per instance or extend the Map control yourself as described in this post. You can then remove the layer than contains the error message so that it's not shown to the user.
public partial class CachedMap : Map
{
public CachedMap() : base()
{
base.LoadingError += (s, e) =>
{
base.RootLayer.Children.RemoveAt(5);
};
}
}
I know it's a very old thread, but anyways...
You can listen for LoadingError event as suggested #keyboardP, search for LoadingErrorMessage control in visual tree and simply hide it.
Map.LoadingError += MapOnLoadingError;
private void MapOnLoadingError(object sender, LoadingErrorEventArgs e)
{
var errorMessage = Map.FindChildOfType<LoadingErrorMessage>();
errorMessage.Visibility = Visibility.Collapsed;
}

Categories