Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Consuming and Persisting State of OData in Windows Phone

DZone's Guide to

Consuming and Persisting State of OData in Windows Phone

· Mobile Zone
Free Resource

Download this comprehensive Mobile Testing Reference Guide to help prioritize which mobile devices and OSs to test against, brought to you in partnership with Sauce Labs.

In this article I will talk about consuming and persist the state of OData in Windows Phone. One can read about OData here. I will use northwind service provided by OData

Let's write code:

Step 1: Create a new Windows Phone Application project. Select Silverlight for Windows Phone installed templates.

Step 2: Add service reference of Nothwind.svc and name it Northwind

http://services.odata.org/Northwind/Northwind.svc/

Step 3: Place ListBox inside content panel of Grid in MainPage.Xaml

<ListBox x:Name="MainListBox" Margin="0,0,-12,0" ItemsSource="{Binding}">
   <ListBox.ItemTemplate>
      <DataTemplate>
         <StackPanel Margin="0,0,0,17" Width="432">
            <TextBlock Text="{Binding Path=CompanyName}" TextWrapping="NoWrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
            <TextBlock Text="{Binding Path=ContactName}" TextWrapping="NoWrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
            <TextBlock Text="{Binding Path=Phone}" TextWrapping="NoWrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
         </StackPanel>
      </DataTemplate>
   </ListBox.ItemTemplate>
</ListBox>

Step 4: Add below using directive in MainPage.Xaml.cs. Second using directive is Namespace of project and name of service reference.

using System.Data.Services.Client;
using WP_Consuming_OData.Northwind;

 Step 5: Define below class level variables.

public partial class MainPage : PhoneApplicationPage
{
   private NorthwindEntities context;
   private readonly Uri northwindUri =
   new Uri(http://services.odata.org/Northwind/Northwind.svc/);
   private DataServiceCollection<Customer> customers;
   private bool isDataLoaded;

 Step 6: Add below method in MainPage.Xaml.cs which will be invoked whenever application is restored. isDataLoaded variable to check if data is already in memory, if data is not in memory the State dictionary will be checked to load, if data is not present in State dictionary also the then OData service will be invoked.

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
   // Get the object data if it is not still loaded.
   if (!this.isDataLoaded)
   {
      object storedState;
      DataServiceState state;
      if (this.State.TryGetValue("DataServiceState", out storedState))
      { 
         // Deserialize the DataServiceState object.
         state = DataServiceState.Deserialize(storedState as string);
         var restoredContext = (NorthwindEntities)state.Context;

         // Set the binding collections from the stored collection.
         var restoredCustomers = state.RootCollections["Customers"] as DataServiceCollection<Customer>;
      this.LoadData(restoredContext, restoredCustomers);
      }
      else
      {
         this.LoadData();
      }
   }
}

Step 7: Add below method in MainPage.Xaml.cs which will serialize and store data serive state.

protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
   var collections = new Dictionary<string, object>();
   collections.Add("Customers", customers);
   this.State["DataServiceState"] = DataServiceState.Serialize(context, collections);
}

Step 8: Now add below LoadData method in MainPage.Xaml.cs which will be invoked when stored data context is used to bind.

public void LoadData(NorthwindEntities context, DataServiceCollection<Customer> customers)
{
   this.context = context;
   this.customers = customers;
   this.isDataLoaded = true;
}

Step 9: LoadData method in MainPage.Xaml.cs will be called to load the data from service first time and in case context is not stored in page state.

private void LoadData()
{
   context = new NorthwindEntities(northwindUri);
   customers = new DataServiceCollection<Customer>(context);
   var query = from cust in context.Customers select cust;
   customers.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(customers_LoadCompleted);
   // Load the Customers feed by executing the LINQ query.
   customers.LoadAsync(context.Customers);
}

Step 10: Add below methon in MainPage.Xaml.cs which occurs when loading of data is completed.

void customers_LoadCompleted(object sender, LoadCompletedEventArgs e)
{
   if (e.Error == null)
   {
      if (customers.Continuation != null)
      {
         customers.LoadNextPartialSetAsync();
      }
      else
      {
         this.LayoutRoot.DataContext = customers;
         this.isDataLoaded = true;
      }
   }
   else
   {
      MessageBox.Show(string.Format("An error has occurred: {0}", e.Error.Message));
   }
}

Step 11: Now run the application and wait for data to load and bind to listbox and then press Start button.

You will get exception Northwind.NorthwindEntities cannot be serialized like below.

WP-Consuming OData

Now open Reference.cs available in below shown path.

Windows Phone - Consuming OData

Add below using directive in Reference.cs

using System.Runtime.Serialization

Now add [DataContract] attribute to NorthwindEntities class

[DataContract]
public partial class NorthwindEntities : global::System.Data.Services.Client.DataServiceContext
{

Step 12: Now run the application and wait for data to load and bind to listbox and then press Start button. This time there won't be any exception.

This ends the article of consuming and persisting state of OData in Windows Phone.

 

 

Analysts agree that a mix of emulators/simulators and real devices are necessary to optimize your mobile app testing - learn more in this white paper, brought to you in partnership with Sauce Labs.

Topics:

Published at DZone with permission of Sumit Dutta, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}