SAP and Xamarin

Challenges of Mobilizing SAP MM with Xamarin - Purchase Orders Page



Overview

In the previous post, we finished the first page of our app, the Login page. In this post, we are going to continue our project, and start implementing the next page, called Purchase Orders in the same way as before. It's going to be a bit more complex, than the Login page, since the page contains a grouped list, and requires a bit more work!

Today lesson

How to feed a grouped listview with data in Xamarin.Forms


Create a Purchase Orders Page

First of all, we are going to create a new page for the list of Purchase Orders , by right clicking on the folder, Pages >> Add >> New Item. Here let's choose the template Visual C# >> Code >> Forms Xaml Page, and name it as PurchaseOrdersPage.


Specify the Root Page of the Application

In the previous post, we defined a single-paged application (with our LoginPage), but now we have 2 different pages, and we would like to navigate back-and-forth between them.

For this reason, we are going to redefine the root page of our app (file App.cs), like this: instead of assigning the LoginPage itself to the MainPage of our app, let's instantiate a NavigationPage, with specifying the LoginPage as the initial page.

As a result, our apps still start with the Login page, but from now on, we are able to navigate back-and-forth among the different pages as well.

namespace SAPGoodsReceipt
{
    public class App : Application
    {
        public App()
        {
            // The root page of your application
            // old definition: MainPage = new LoginPage();
            MainPage = new NavigationPage(new LoginPage());
        }
        ...
    }
}

So now, we can navigate between our pages, but using the class, NavigationPage has a side-effect, namely it places a navigation bar at the top of our pages as well, that we want to avoid on the login page, since we don't need navigation bar on this page.

For this, there is nothing to do, than setting the property of the NavigationPage class, named HasNavigationBar to false within the file, LoginPage.xaml.cs.

namespace SAPGoodsReceipt
{
    public partial class LoginPage : ContentPage
    {
        public LoginPage()
        {            
            InitializeComponent();

            NavigationPage.SetHasNavigationBar(this, false);
        }
    }
}


Set Navigation to the Purchase Orders Page

After wrapping our LoginPage into a NavigationPage, we are a step away from navigating among our pages. In order to navigate from the Login page to our new Purchase Orders page using the button, Login we have to catch the Clicked event of our button.

But how to refer to it? Button1, Button3, ButtonLogin, ...?

It's simple, first we need to provide a name, by setting the x:Name property of our button to, let's say LoginButton, in the XAML of the LoginPage:

Now, we can easily refer to our button and its events, and specify an event handler with a simple lambda expression. Within the lambda expression, now we are going to simply navigate to our new PurchaseOrdersPage.

Note

Later on, we will perform an authentication here before navigating to the next page (of course in case of success only).
namespace SAPGoodsReceipt
{
    public partial class LoginPage : ContentPage
    {
        public LoginPage()
        {            
            InitializeComponent();

            NavigationPage.SetHasNavigationBar(this, false);

            LoginButton.Clicked += (sender, e) => {
                Navigation.PushAsync(new PurchaseOrdersPage());
            };
        }
    }
}


Create Models

If you are ready, then we can go ahead and make some preparation for the Purchase Orders list.

To keep our projects transparent, we are going to create a new folder for the models. For this, let's create a new folder, named Models under our PCL project (by right clicking on the project >> Add >> New Folder), where we are going to place the different models of our app.



We are going to create two models, one for defining a single Purchase Order entity, and another for representing a group with a key and the list of its related items.

For this, let's create two models, named Group and PurchaseOrder, by right clicking on the folder, Models >> Add >> New Item. Here let's choose the template Visual C# >> Code >> Class.



The Purchase Order model is going to be very simple, with a few properties, like Id, Vendor, GroupType, NumberOfItems, TotalPrice (note: we are going to extend it if it's appropriate).

The grouped listview approach in Xamarin.Forms originates from James Montemagno. The part of the solution is to create a complex model that we use for storing each K key with the associated list of T items.


Construct the Purchase Orders Page in XAML

Alright, now we have everything to build our Purchase Orders page directly in XAML.

First, we are going to set a title for our page, like Purchase Orders (this will be displayed on the navigation bar). Then we are going to place a ListView control into our XAML defintion that is used to display scrolling lists of data, like in our case the list of Purchase Orders, where:

  • we name it as PurchaseOrdersListView (so we are able to refer it later),
  • set the property IsGroupingEnabled to true (it's very important, if we want grouped list)
  • and at last, we set the binding for text of the group headers that is going to be the Group.Key property ("1. Today Deliveries", "2. Late Deliveries").

Since we want to use custom cells in the grouped listview, we need to define and customize the appearance of a cell for ourselves (we cannot use the built-in cells), in the following way:

We start the cell definition with a horizontal main Stacklayout that we place 15dip away from the left and right sides of the screen (to ensure the content won't slip off the screen).

Within the main StackLayout, we place two sub StackLayout centered vertically, the first will hold the Vendor and the Number of items, and the second one will hold the Total price that is aligned to the end (or with other words, to the right side).

So as I have already told you, in the first sub StackLayout, we place the infos: the Vendor and the Number of items. We are going to display both of them using simple Labels. To bind the content of the Labels to the properties of the Purchase Order model, we set the binding context like this: ...Text="{Binding Property_Name}"...

Then, we place another Label into the second sub StackLayout for displaying the Total price, where apply the same binding method (we map the content of the label to the PurchaseOrder.TotalPrice property).


Implement the Code-Behind

Now, we arrived to the last step, namely feeding the grouped listview with data that we are going to implement, in the code-behind file, PurchaseOrdersPage.xaml.cs.

To feed a listview, we need to use its ItemsSource property. Now, we simply delegate the work of collecting the required data to a method, named GetGroupedPurchaseOrders.

Note

Later on, we will extract this logic into a PurchaseOrder repository, since collecting the required data, it's not the view's responsibility.
namespace SAPGoodsReceipt.Pages
{
    public partial class PurchaseOrdersPage : ContentPage
    {
        public PurchaseOrdersPage()
        {
            InitializeComponent();

            PurchaseOrdersListView.ItemsSource = GetGroupedPurchaseOrders();
            BindingContext = this;
        }

        ...
    }
}

Since, we will get the Purchase Orders in list format from SAP, and we want grouped list of Purchase Orders, we need to group them before binding it the ItemsSource property. This takes place in this method:

  • first we save the simple list of Purchase Orders,
  • then we sort and group them based on the GroupType property ("1. Today Deliveries", "2. Late Deliveries"),
  • and at last, we create a collection of the groups.

As you can see, now we use an ObservableCollection instead of a simple List, since the ObservableCollection is data collection that provides notifications when items get added, removed, or when the whole list is refreshed, so we don't need to deal with refreshing the UI, when the collection changes.

To feed the listview with sample data, now let me simply create some sample records only in the memory.


Run Your Android and iOS Apps

Now comes the best part of building native mobile apps, namely let's BUILD and RUN it! :) I attached two screenshots about the running apps, one for the Android, and another for the iOS app.


Summary

It was a long story, but now we have a running app with two pages! I hope, you could follow me, and everything went fine. If not, then don't hesitate to leave me a comment below!

Next, we are going to work on the Purchase Order Items page.

Stay tuned, keep reading! If you want to get notification about the newest posts, follow us or subscribe to our newsletter! If you liked it, please share it! Thanks!

blog comments powered by Disqus