Wednesday, February 5, 2014

How to dynamically set the application start page on Windows Phone 8

Introduction

The default start page for an application is set in WMAppManifest.xml - in the DefaultTask node of theNavigationPage tag. While having a static start page is ideal for some apps, there are many cases where it is useful to be able to dynamically select the start page.
For example, it is often useful to have:
  • a different start page for when user login credentials are stored from when they are not stored
  • a "wizard" start sequence for the first time the user activates the app
The article shows how to change the remove the default page and dynamically set the new start page in C# code. It uses the context of an app which has different screens for logging in (Login.xaml) and for when they have already entered their details (HomeScreen.xaml).
Note: It is also possible to have a default page which dynamically configures itself. While this may be suitable in many cases, usually it is better for code maintenance to have separate pages.

Removing the default page

The first step is to remove the default page that us set by default in the manifest file (WMAppManifest.xml) in apps created from the standard templates.
Simply remove NavigationPage="MainPage.xaml" from the code below.
<Tasks>
      <DefaultTask Name="_default" NavigationPage="MainPage.xaml" />
</Tasks>


For instance:
<Tasks>
      <DefaultTask Name="_default" />
</Tasks>

Set the Start Page / View after the App has initialised

The start page is specified in InitializePhoneApplication() by calling RootFrame.Navigate() (after other initialisation has completed).
RootFrame.Navigate(new Uri("/StartPage.xaml", UriKind.RelativeOrAbsolute));
The example below shows a different start page being selected based on a check of the application settings to determine if login information has already been stored (Login status is checked with IsolatedStorageSettings.ApplicationSettings.Contains("islogin").)
  private void InitializePhoneApplication()
        {
            if (phoneApplicationInitialized)
                return;
 
            // Create the frame but don't set it as RootVisual yet; this allows the splash
            // screen to remain active until the application is ready to render.
            RootFrame = new PhoneApplicationFrame();
            RootFrame.Navigated += CompleteInitializePhoneApplication;
 
            // Handle navigation failures
            RootFrame.NavigationFailed += RootFrame_NavigationFailed;
 
            // Handle reset requests for clearing the backstack
            RootFrame.Navigated += CheckForResetNavigation;
 
            // Ensure we don't initialize again
            phoneApplicationInitialized = true;
 

           // Set the Start Page according to the below code.
//Here, If IsolatedStorageSettings contains "isLogin" key, then it is redirected to HomeScreen that normally comes after login screen.            Uri uri;
            if (IsolatedStorageSettings.ApplicationSettings.Contains("islogin"))
            {
                if (!(Convert.ToString(IsolatedStorageSettings.ApplicationSettings["islogin"]).ToLower() == "yes"))
                {
                    RootFrame.Navigate(new Uri("/LoginScreen.xaml", UriKind.RelativeOrAbsolute));
                }
                else
                {
                    RootFrame.Navigate(new Uri("/HomeScreen.xaml", UriKind.RelativeOrAbsolute));               
                }
            }
            else
            {
                RootFrame.Navigate(new Uri("/LoginScreen.xaml", UriKind.RelativeOrAbsolute));
            }          
        }


Tuesday, February 4, 2014

Consume data from REST service, Serialize / Deserialize the json string in Windows Phone 8 Apps


CommonClass:
Below are the Microsoft built-in Generic Methods to serialize / deserialize JSON data in Windows Phone 8:
        public static T DeserializeJSon<T>(string jsonString)
        {
            DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
            MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
            T obj = (T)ser.ReadObject(stream);
            return obj;
        }

        public static string SerializeToJson<T>(T obj)
        {
            MemoryStream stream = new MemoryStream();
            DataContractJsonSerializer jsonSer =
            new DataContractJsonSerializer(typeof(T));
            jsonSer.WriteObject(stream, obj);
            stream.Position = 0;
            StreamReader sr = new StreamReader(stream);
            var json = sr.ReadToEnd();
            return json;
        }


Now, to get the data from REST and deserialize the result json, back to object in Windows Phone 8:

        public static void GetDataAsync<T>(string restServiceMethodUrl)
        {
            var jsonResult = string.Empty;
            var webClient = new WebClient();

            webClient.DownloadStringAsync(new Uri(restServiceMethodUrl));
            webClient.DownloadStringCompleted += (s, e) =>
            {
                if (e.Error != null)
                {
                    jsonResult = e.Result.ToString();
                    var objActualData = DeserializeJSon<TestViewModel>(jsonResult);
                }
            };
        }


To post / get data basis with input parameters, below is the method in Windows Phone 8:

        public static void PostDataAsync<T>(Uri uri, ObjectAsInput obj)
        {
            var jsonResult = string.Empty;
            var webClient = new WebClient();
            var jsonDataInput = SerializeToJson<ObjectAsInput >(obj);

            if (!string.IsNullOrEmpty(jsonDataInput))
            {
                webClient.Headers["Content-Type"] = "application/json; charset=utf-8";
                webClient.UploadStringAsync(uri, jsonDataInput);
                webClient.UploadStringCompleted += (s, e) =>
                {
                    if (e.Error != null)
                    {
                        jsonResult = e.Result.ToString();
                        var actualData = DeserializeJSon<TestViewModel>(jsonResult );
                    }

                };
            }
        }