Xamarin Guide 8. Change the App.cs to App.xaml

Scope

This Xamarin Workshop Guide was created for the The Portuguese National Meeting of IT Students (ENEI) by Sara Silva which original content is available here. With the goal to extend it to the global community, it was published in a new project called Xam Community Workshop, which the main goal is to any developer, or user group customize it to theirs events.

8. Change the App.cs to App.xaml

In this step you will learn how to change the App.cs to have the App.xaml file, which will define the Xamarin Forms application.

In the ENEI.SessionsApp project is possible to find the App.cs file which define the application. It is a simple class defined in a *.cs file, which can be defined using a XAML approach. For it you need to create a new XAML page as described in figure 51 and figure 52:

**Figure 51:** Add new item (using Visual Studio) Figure 51: Add new item (using Visual Studio)

**Figure 52:** Add new Forms Xaml Page called App (using Visual Studio)Figure 52: Add new Forms Xaml Page called App (using Visual Studio)

The result will be something as following:

App.xaml

 <!--?<span class="hiddenSpellError" pre="" data-mce-bogus="1"-->xml version="1.0" encoding="utf-8" ?&gt;
    
       <label>
   </label>

App.xaml.cs

 public partial class App : ContentPage
 {
    public App()
    {
        InitializeComponent();
    }
 }

At this moment, it is a content page that is not our goal, but it is the workaround to create the App.xaml and App.xaml.cs files. Now to create the Xamarin Forms application based in the XAML approach we need to change the code above, as following:

App.xaml

<!--?<span class="hiddenSpellError" pre="" data-mce-bogus="1"-->xml version="1.0" encoding="utf-8" ?&gt;
  

App.xaml.cs

public partial class App : Application
{
    public App()
    {
        InitializeComponent();
    }
}

With it, you will have to App class that inherits from Xamarin.Forms.Application, to avoid it, you should delete the App.cs file, but before we need to move the code from the App.cs to App.xaml.cs, which result will be something as following:

public class App : Application
{
    public App()
    {
        // The root page of your application
        MainPage = new NavigationPage(new SessionsView())
        {  
            BarBackgroundColor = Color.White,
            BarTextColor = Color.Black,
            BackgroundColor = Color.White,
        };
    }

    protected override void OnStart()
    {
        // Handle when your app starts
    }

    protected override void OnSleep()
    {
        // Handle when your app sleeps
    }

    protected override void OnResume()
    {
        // Handle when your app resumes
    }
}

If you run the application it must behave as before.

Xamarin Guide 7. Add support for WinRT Apps

Scope

This Xamarin Workshop Guide was created for the The Portuguese National Meeting of IT Students (ENEI) by Sara Silva which original content is available here. With the goal to extend it to the global community, it was published in a new project called Xam Community Workshop, which the main goal is to any developer, or user group customize it to theirs events.

7. Add support for WinRT Apps

In this step you will learn how to add support to WinRT apps, which means you will create an Universal apps that will use Xamarin Forms for Windows (Preview).

To start, create a new project based in an Universal App template, as described in figure 39 and figure 40:

Create new project

Figure 39: Create new project

Blank App (Universal App)

Figure 40: Blank App (Universal App)

The result will be:

The solution

Figure 41: The solution

Now, you will add the ENEI.SessionsApp reference to the WinRT project, as described in figure 42 and figure 43:

Add Reference

Figure 42: Add Reference

Selecting the ENEI.SessionApp

Figure 43: Selecting the ENEI.SessionApp

In the Windows Phone 8.1 (WinRT) app we can get an error as following:

Error adding ENEI.SessionsApp

Figure 44: Error adding ENEI.SessionsApp

This error means that the ENEI.SessionsApp is a portable class library (PCL) that does not have support to Windows Phone 8.1 (WinRT). This way, you need to change the PCL project (in Properteis) to support this target, as described in figure 45:

Add support to Windows Phone 8.1 (WinRT)

Figure 45: Add support to Windows Phone 8.1 (WinRT)

After it, you will have the references added to each project, as following:

The references

Figure 46: The references

Before you create code, you need to install the Xamarin Forms Windows (Preview) NuGet Package as following:

Opening the “Manage NuGet Packages…”

Figure 47: Opening the “Manage NuGet Packages…”

Installing the Xamarin Forms Windows (Preview)

Figure 48: Installing the Xamarin Forms Windows (Preview)

The Xamarin Forms Windows (Preview) installed

Figure 49: The Xamarin Forms Windows (Preview) installed

Let’s do some code!

In general, you should do not so many changes to have the WinRT apps. First, you need to start by doing the Xamarin Forms setup, this way you need change the OnLaunched method in the App.xaml.cs has following:

 protected override void OnLaunched(LaunchActivatedEventArgs e)
    {
       #if DEBUG
        if (System.Diagnostics.Debugger.IsAttached)
        {
            this.DebugSettings.EnableFrameRateCounter = true;
        }
      #endif

        Frame rootFrame = Window.Current.Content as Frame;

        // Do not repeat app initialization when the Window already has content,
        // just ensure that the window is active
        if (rootFrame == null)
        {
            // Create a Frame to act as the navigation context and navigate to the first page
            rootFrame = new Frame();

            // TODO: change this value to a cache size that is appropriate for your application
            rootFrame.CacheSize = 1;


            global:Xamarin.Forms.Forms.Init(e);


   ….

Like in the others platform, the Init method will initialized the Xamarin Forms, in this case is need to send the LaunchActivatedEventArgs.

And we need to change the MainPage contructor, from each WinRT app, to:

   public MainPage()
    {
        this.InitializeComponent();

        this.NavigationCacheMode = NavigationCacheMode.Required;
        LoadApplication(new ENEI.SessionsApp.App());
    }

and the page type must be change to:

  • In Windows Phone 8.1 (WinRT):
<forms:WindowsPhonePage
       x:Class="ENEI.SessionsApp.WinRT.MainPage"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:forms="using:Xamarin.Forms.Platform.WinRT"
       xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
       mc:Ignorable="d"
       Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">            

    </forms:WindowsPhonePage>
  • In Windows 8.1 Store App (WinRT):
 <forms:WindowsPage
     x:Class="ENEI.SessionsApp.WinRT.MainPage"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:forms="using:Xamarin.Forms.Platform.WinRT"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     mc:Ignorable="d"
     Foreground="Black"
     Background="White">
  </forms:WindowsPage>

Now, it is need to define the background color from the NavigationPage to white, which should be defined from the beginner:

      MainPage = new NavigationPage(new SessionsView())
        {  
            BarBackgroundColor = Color.White,
            BarTextColor = Color.Black,
            BackgroundColor = Color.White,
        };

At this moment, you will see the header in the right way but the images from the menu are not displayed, it because each image was defined by:

 <Image Grid.Column="7">
                <Image.WidthRequest>
                  <OnPlatform Android="30"
                              WinPhone="48"
                              iOS="30"
                              x:TypeArguments="x:Double" />
                </Image.WidthRequest>
                <Image.HeightRequest>
                  <OnPlatform Android="30"
                              WinPhone="48"
                              iOS="30"
                              x:TypeArguments="x:Double" />
                </Image.HeightRequest>
                <Image.Source>
                  <OnPlatform x:TypeArguments="ImageSource">
                    <OnPlatform.iOS>
                      <FileImageSource File="ic_action_list.png" />
                    </OnPlatform.iOS>
                    <OnPlatform.Android>
                      <FileImageSource File="ic_action_list.png" />
                    </OnPlatform.Android>
                    <OnPlatform.WinPhone>
                      <FileImageSource File="Images/ic_action_list.png" />
                    </OnPlatform.WinPhone>
                  </OnPlatform>
                </Image.Source>
                <Image.GestureRecognizers>
                  <TapGestureRecognizer x:Name="DetailsGesture"
                                        CommandParameter="{Binding}"
                                        Tapped="DetailsGesture_OnTapped" />
                </Image.GestureRecognizers>
              </Image>

Which are using OnPlatform to set the image’s source and the image’s height and width. In the preview version used, is not possible to use but in future it will work to Windows apps like works for the others platforms.

This way, you need to create a workaround to make sure the images will be load and it will be use converters, as following:

 <ContentPage.Resources>
        <ResourceDictionary>
          <converters:FavoriteImageConverter x:Key="FavoriteImageConverter" />
          <converters:ImageSizeConverter x:Key="ImageSizeConverter"/>
          <converters:ImageUrlConverter x:Key="ImageUrlConverter"/>
          <converters:RowHeightConverter x:Key="RowHeightConverter"/>
        </ResourceDictionary>
     </ContentPage.Resources>

And

          <Image Grid.Column="7"
                  Source="{Binding Converter={StaticResource ImageUrlConverter}, ConverterParameter=Details}"
                  HeightRequest="{Binding Converter={StaticResource ImageSizeConverter}}"
                  WidthRequest="{Binding Converter={StaticResource ImageSizeConverter}}">
                <Image.GestureRecognizers>
                  <TapGestureRecognizer x:Name="DetailsGesture"
                                        CommandParameter="{Binding}"
                                        Tapped="DetailsGesture_OnTapped" />
                </Image.GestureRecognizers>
              </Image>

Where the converters are defined by:

The ImageSizeConverter to define the Height and the Width for the images

public class ImageSizeConverter:IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value != null)
        {

            if (Device.OS == TargetPlatform.Android || Device.OS == TargetPlatform.Windows)
            {
                return 48;
            }
            if (Device.OS == TargetPlatform.iOS)
            {
                return 30;
            }
        }
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}            

The ImageUrlConverter, to define the path for the images:

public class ImageUrlConverter:IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (parameter !=null && !string.IsNullOrEmpty(parameter.ToString()))
        {
            var imageUrl = string.Empty;
            switch (parameter.ToString())
            {
                case "Like":
                    imageUrl= Device.OS == TargetPlatform.WinPhone || Device.OS == TargetPlatform.Windows ?
                    "Images/ic_action_like.png":
                    "ic_action_like.png";
                    break;
                case "Share":
                    imageUrl = Device.OS == TargetPlatform.WinPhone || Device.OS == TargetPlatform.Windows ?
                   "Images/ic_action_share_2.png" :
                   "ic_action_share_2.png";
                    break;
                case "Details":
                    imageUrl = Device.OS == TargetPlatform.WinPhone || Device.OS == TargetPlatform.Windows ?
                   "Images/ic_action_list.png" :
                   "ic_action_list.png";
                    break;
            }

            return ImageSource.FromFile(imageUrl);
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

The RowHeightConverter to define the size of the row from the ListView:

public class RowHeightConverter:IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value != null)
        {

            if (Device.OS == TargetPlatform.Android || Device.OS == TargetPlatform.iOS)
            {
                return 150;
            }
            if (Device.OS == TargetPlatform.WinPhone)
            {
                return 180;
            }
            if (Device.OS == TargetPlatform.Windows)
            {
                return 200;
            }
        }
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

At this moment if you run the applications you will have something as following:

Xamarin Workshop - 1010 ENEI Sessions App

Figure 50: The WinRT apps

Xamarin Guide 6. Add splash screen, name and version

Scope

This Xamarin Workshop Guide was created for the The Portuguese National Meeting of IT Students (ENEI) by Sara Silva which original content is available here. With the goal to extend it to the global community, it was published in a new project called Xam Community Workshop, which the main goal is to any developer, or user group customize it to theirs events.

6. Add splash screen, name and version

In this step you will learn how to create the splash screen to all platforms and you learn to define the name & version of the application.

Define the splash screen

The splash screen in mobile application is the first screen that the user will see, in some applications it is used to load initial data. It is defined in different ways to each platform and for each one you will learn how it works:

  • In ENEI.SessionsApps.iOS

In iOS and iPad applications is possible to define launch images as splash screen in the Info.plist. It is described in the following figures:

Figure 6.1: Defining Launch Images using Visual Studio

Figure 6.1: Defining Launch Images using Visual Studio

Figure 6-2: Defining Launch images in Xamarin Studio

Figure 6-2: Defining Launch images in Xamarin Studio

• In ENEI.SessionsApps.Android

By default, in Android applications, there is not splash screen concept. To solve it, is possible to create an Activity that will be a splash screen page.

In the ENEI.SessionsApp create the SplashScreen class, as following:

[Activity(Label = "1010 ENEI", MainLauncher = true, NoHistory = true, Theme = "@style/Theme.Splash",
 ConfigurationChanges = ConfigChanges.ScreenSize, ScreenOrientation = ScreenOrientation.Portrait)]
public class SplashScreen : Activity
{
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        var intent = new Intent(this, typeof(MainActivity));
        StartActivity(intent);
        Finish();
    }
}

In the Resources\Values folder create an xml file called Style, as following:

<!--?<span class="hiddenSpellError" pre="" data-mce-bogus="1"-->xml version="1.0" encoding="utf-8" ?&gt;

Then change the MainActivity to:

[Activity(Label = "1010 ENEI", Theme = "@style/Theme.ENEI", ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        global::Xamarin.Forms.Forms.Init(this, bundle);
        ActionBar.SetIcon(Resource.Drawable.ic_action_users);
        LoadApplication(new App());
    }
}

If you run the Android application you will get the “splash screen” defined, similar to the others platforms.

See more about it in this article Creating a Splash Screen.

  • In ENEI.SessionsApps.WinPhone

Windows Phone application supports splash screen by default, this way it only required a nice image which will be showed to the user.

Figure 6-3: The SplashScreenImage

Figure 6-3: The SplashScreenImage

Define the name and the version for each platform

To define the name & the version for each platform you will need:

  • In ENEI.SessionsApps.iOS

Open the Info.plist or the project’s properties as described in figure 6-4 and figure 6-5:

Figure 6-4: Defining Name & Version using Xamarin Studio (Info.plist)

Figure 6-4: Defining Name & Version using Xamarin Studio (Info.plist)

Figure 6-5: Defining Name & Version using Visual Studio (project’s properties)

Figure 6-5: Defining Name & Version using Visual Studio (project’s properties)

  • In ENEI.SessionsApp.Android

Open the project’s properties as described in figure 6-6 and figure 6-7:

Figure 6-6: Defining Name & Version using Xamarin Studio (project’s properties)

Figure 6-6: Defining Name & Version using Xamarin Studio (project’s properties)

Figure 6-7: Defining Name & Version using Visual Studio (project’s properties)

Figure 6-7: Defining Name & Version using Visual Studio (project’s properties)

  • In ENEI.SessionsApps.WinPhone

Open the manifest file as describe in the figure 6-8 and figure 6-9:

Figure 6-8: Defining Name in the manifest file

Figure 6-8: Defining Name in the manifest file

Figure 6-9: Defining Version in the manifest file

Figure 6-9: Defining Version in the manifest file

Yes, ….. I am Xamarin MVP

Yesterday it was a unforgettable day, I got the Xamarin MVP award, and it is always a pleasure to be part of great community like Xamarin’s Community :)

Xamarin MVP

If you want to read the news about it, see this article:

A very warm welcome to our newest Xamarin MVPs! Thank you for all of your contributions to our community:

See all Xamarin MVP here and you can nominate yourself or a colleague here.

I was Microsoft Azure Technical Guru – March 2015

The The Microsoft TechNet Guru Awards! (March 2015) is out! And for the third time in this year, my article was selected! Really thanks for the words about my work, it is really motivating.

Technical Gur

Engage!

Xamarin Guide 5. Add ShareService

Scope

This Xamarin Workshop Guide was created for the The Portuguese National Meeting of IT Students (ENEI) by Sara Silva which original content is available here. With the goal to extend it to the global community, it was published in a new project called Xam Community Workshop, which the main goal is to any developer, or user group customize it to theirs events.

Guides 5. Add ShareService

An application which allow to share content in social networks brings more value to the users, because allow to share with others something the user think is important or relevant. An application for events like 1010 ENEI Sessions App could not miss this feature.

Each platform has your own implementation to share content in social network. This means, we need to create an abstraction of the share feature to use it in ENEI.SessionsApp and then in each platform we need to implement that abstraction. Let’s see how the Abstraction Pattern can be created! In ENEI.SessionsApp project, create the interface IShareService as following:

public interface IShareService 
{ 
void ShareLink(string title, string status, string link); 
}

Then is required to create the implementation of the IShareService in each platform. Let’s define the following implementation by platform:

Windows Phone

[assembly: Dependency(typeof(ShareService))]
namespace ENEI.SessionsApp.WinPhone.Services
{
    public class ShareService : IShareService
    {
      public void ShareLink(string title, string status, string link)
      {
        var task = new ShareLinkTask { Title = title, Message = status, LinkUri = new Uri(link) };
        Device.BeginInvokeOnMainThread(() =>
        {
            try
            {
                task.Show();
            }
            catch (Exception ex)
            {
             // todo handle the error   
            }
        });
    }
  }
}

Android

 [assembly: Dependency(typeof(ShareService))]
 namespace ENEI.SessionsApp.Droid.Services
 {
   public class ShareService : IShareService
   {
     public void ShareLink(string title, string status, string link)
     {
        var intent = new Intent(global::Android.Content.Intent.ActionSend);
        intent.PutExtra(global::Android.Content.Intent.ExtraText, string.Format("{0} - {1}", status ?? string.Empty, link ?? string.Empty));
        intent.PutExtra(global::Android.Content.Intent.ExtraSubject, title ?? string.Empty);
        intent.SetType("text/plain");
        intent.SetFlags(ActivityFlags.ClearTop);
        intent.SetFlags(ActivityFlags.NewTask);
        Android.App.Application.Context.StartActivity(intent);
    }
  }
}

iOS

[assembly: Dependency(typeof(ShareService))]
namespace ENEI.SessionsApp.iOS.Services
{
public class ShareService : IShareService
{
    public void ShareLink(string title, string status, string link)
    {
        var actionSheet = new UIActionSheet("Share on");
        foreach (SLServiceKind service in Enum.GetValues(typeof(SLServiceKind)))
        {
            actionSheet.AddButton(service.ToString());
        }
        actionSheet.Clicked += delegate(object a, UIButtonEventArgs b)
        {
            SLServiceKind serviceKind = (SLServiceKind)Enum.Parse(typeof(SLServiceKind), actionSheet.ButtonTitle(b.ButtonIndex));
            ShareOnService(serviceKind, title, status, link);
        };
        actionSheet.ShowInView(UIApplication.SharedApplication.KeyWindow.RootViewController.View);
    }

    private void ShareOnService(SLServiceKind service, string title, string status, string link)
    {
        if (SLComposeViewController.IsAvailable(service))
        {
            var slComposer = SLComposeViewController.FromService(service);
            slComposer.SetInitialText(status);
            slComposer.SetInitialText(title != null ? string.Format("{0} {1}", title, status) : status);
            if (link != null)
            {
                slComposer.AddUrl(new NSUrl(link));
            }
            slComposer.CompletionHandler += (result) =>
            {
                UIApplication.SharedApplication.KeyWindow.RootViewController.InvokeOnMainThread(() =>
                {
                    UIApplication.SharedApplication.KeyWindow.RootViewController.DismissViewController(true, null);
                });
            };
            UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(slComposer, true, null);
        }
    }
  }
}

This way, we are ready to call the share service in the SessionsView using DependencyService, as following: private void ShareGesture_OnTapped(object sender, EventArgs e) { var tappedEventArg = e as TappedEventArgs; if (tappedEventArg != null) { var session = tappedEventArg.Parameter as Session; if (session != null) { var shareService = DependencyService.Get(); if (shareService != null) { var status = string.Format(“Não percas a sessão {0} de {1}.”, session.Name, session.Speaker.Name); shareService.ShareLink(“ENEI 2015″, status, “https://enei.pt/“); } } } }

The DependencyService only will get the implementation from the IShareService because the implementation from each platform was registered using: [assembly: Dependency(typeof(ShareService))]

At this moment the 1010 ENEI Sessions App has support to share session in social network!

Xamarin Guide 4. Create the SessionDetailsView

Scope

This Xamarin Workshop Guide was created for the The Portuguese National Meeting of IT Students (ENEI) by Sara Silva which original content is available here. With the goal to extend it to the global community, it was published in a new project called Xam Community Workshop, which the main goal is to any developer, or user group customize it to theirs events.

Guides 4. Create the SessionDetailsView

In the last step, you created the menu for each Session and it was created the “Details” option, which has the goal to show the details from a selected session.

Let’s create the SessionDetailsView!

Create a new Xaml page, like it you did to create the SessionsView page. Then open the SessionDetailsView and you should have something as following:

<!--?<span class="hiddenSpellError" pre="" data-mce-bogus="1"-->xml version="1.0" encoding="utf-8" ?&gt;
    

Then create the content, as following:

<!--?<span class="hiddenSpellError" pre="" data-mce-bogus="1"-->xml version="1.0" encoding="utf-8" ?&gt;
    
    
      
        
          
        
        <img alt="" />
        <label>
      </label>
      
            <img alt="" />
                
                    
                
                
                    
                
            
            
                <label>
                <label>
            </label></label>

And in code behind define the BindingContext and the Title, as following:

public partial class SessionDetailsView : ContentPage
{
    private readonly Session _session;

    public SessionDetailsView(Session session)
    {
        _session = session;
        InitializeComponent();
        Title = session.Name;
        BindingContext = session;
    }
}

This page will have the BindingContext defined with session object, but could be the page as in SessionsView.

The Details gesture

Now that you have the new page created, you need to connect the both pages and it is possible through the “Detail” option for each session in Listview. This way, in the SessionsView we need to use the details gesture to navigate from the SessionsView to the SessionDetailsView, sending the selected session. The implementation can be something as following:

 private void DetailsGesture_OnTapped(object sender, EventArgs e)
    {
        var tappedEventArg = e as TappedEventArgs;
        if (tappedEventArg != null)
        {
            var session = tappedEventArg.Parameter as Session;
            if (session != null)
            {
                Navigation.PushAsync(new SessionDetailsView(session), true);
            }
        }
    }

Running the application

At this moment, you should navigate to the Session details view, which result should be as described in figure 38:

Xamarin Workshop - Figure 38

Figure 38: The Windows Phone, iOS and Android applications

The navigation from SessionDetailsView is made using the back button provided in iOS and Android pages and by physical back button from Windows Phone, which do not require implementation.

Xamarin Guide 3. Create the SessionsView

Scope

This Xamarin Workshop Guide was created for the The Portuguese National Meeting of IT Students (ENEI) by Sara Silva which original content is available here. With the goal to extend it to the global community, it was published in a new project called Xam Community Workshop, which the main goal is to any developer, or user group customize it to theirs events.

In this step, you will create the user interface to the SessionsView (which is the main page) to show the data defined in the last step.

3.1. Create the Xaml page

In Xamarin Studio, select the ENEI.SessionsApp project and create a folder called “Views”, as described in figure 25 and figure 26:

Xamarin Workshop - Figure 25

Figure 25: Creating new folder

Xamarin Workshop - Figure 26

Figure 26: The Views folder in the project

Then select the folder “Views” , do a double click with the mouse to open the context and the click in “Add”> “New File…” as described in figure 27:

Xamarin Workshop - Figure 27

Figure 27: Add new file

Select “Forms ContentPage Xaml”, as following:

Xamarin Workshop - Figure 28

Figure 28: Adding a Xaml page

The result will be something as following:

Xamarin Workshop - Figure 29

Figure 29: The xaml page code

The SessionsView xaml is defined by:

  • The xaml file which define the user interface
  • The cs file which define the code behind

This approach is really useful when designers and developers work together, and using MVVM pattern it allow to have UI separated from the behavior of the page.

See more about Xaml in this article Xamarin.Forms Xaml Basics.

Now let’s change the App.cs in ENEI.SessionsApp to use the SessionsView:

public class App : Application
{
    public App()
    {
        // The root page of your application
        MainPage = new NavigationPage(new SessionsView())
        {
            BarBackgroundColor = Color.White,
            BarTextColor = Color.Black
        };
    }

In this case, you defined the MainPage with a NavigationPage which content is defined by SessionView. The NavigationPage is required when the application required navigation between page and the application should have only one NavigationPage. At this moment, if you run the application you will not have content and you should have something like as described in figure 30:

Xamarin Workshop - Figure 30

Figure 30: The xaml page code

Now let’s define the UI…

3.2. Create the Header

The first thing you should define is the Title and the Icon used in the header of the page, something like as following:

Xamarin Workshop - Figure 31

Figure 31: The header

Which code can be:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="ENEI.SessionsApp.Views.SessionsView"
         Title="1010 ENEI || Sessões"
         BackgroundColor="White"
         Icon="ic_action_users.png">

This will be showed in Android and in iOS but for Windows Phone 8.0 we need to create a workaround for it, as we will see below.

In Android, more specific in the MainActivity is required (in this case) to set the Icon in ActionBar as following: ActionBar.SetIcon(Resource.Drawable.ic_action_users);

The SessionsView is a ContentPage which is a simple page provided by Xamarin Forms API (see more in Xamarin Forms Gallery). To define its content, you should use controls layouts like StackLayout or Grid, for example.

Xamarin Workshop - Figure 30

Figure 32: Control Layouts

This way, let’s choose the Grid as control layout to define two rows and one columns, where:

  • The first row has the header for Windows Phone (hidden to the others platforms)
  • The second row has the ListView to show the sessions.

The code for it will be something like as following:

<?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="ENEI.SessionsApp.Views.SessionsView"
         Title="1010 ENEI || Sessões"
         BackgroundColor="White"
         Icon="ic_action_users.png">
       <Grid BackgroundColor="White">
         <Grid.RowDefinitions>
           <RowDefinition Height="Auto" />
           <RowDefinition Height="*" />
         </Grid.RowDefinitions>
       <!-- Title - Only for WP-->
       <StackLayout Grid.Row="0" Orientation="Horizontal" Padding="20,10,0,0">
       <StackLayout.IsVisible>
          <OnPlatform Android="false"
                WinPhone="true"
                iOS="false"
                x:TypeArguments="x:Boolean" />
       </StackLayout.IsVisible>
       <Image WidthRequest="48" 
         HeightRequest="38" 
         Source="Images/ic_action_users.png"/>
       <Label FontSize="Large" FontAttributes="Bold"
              TextColor="Black">
       <OnPlatform Android=""
                WinPhone="1010 ENEI || Sessões"
                iOS=""
                x:TypeArguments="x:String" />
        </Label>
       </StackLayout>
       <!-- ListView will be defined here -->
      </Grid>
    </ContentPage>
Defining the Images for each platform

In the last step you used the image “ic_action_users.png” which need to be add to each project (ENEI.SessionApp.Android, ENEI.SessionApp.iOS and ENEI.SessionApp.WinPhone). This way, each app will have its own images, which should be defined following the platform specifications, i.e., each image should provide the right resolution by platform.

Get the images & assets by platform here, and see more about this subject in this article.

At this moment, you should have

Xamarin Workshop - Figure 33

Figure 33: The Windows Phone, iOS and Android applications

3..3. Create the Listview

The next step is to define the list of the session from the 1010 ENEI, which were defined in the topic “The Data Source”. To show the list of the session you will use a ListView which must have:

  • ItemsSource defined with the list of sessions
  • ItemTemplate defined with the template for each row

Let’s define the first version of the ListView as following:

<!-- ListView will be defined here -->
<ListView x:Name="SessionsList"
             Grid.Row="1"
             ItemSelected="SessionsList_OnItemSelected"
             ItemsSource="{Binding Sessions}"
             SeparatorColor="#0094FF">
  <!--
            Setting the HasUnevenRows property tells the list view to render
            each cell with a different height.
        -->
  <ListView.RowHeight>
    <OnPlatform Android="150"
                WinPhone="180"
                iOS="150"
                x:TypeArguments="x:Int32" />
  </ListView.RowHeight>
</ListView>

The Listview has the name “SessionsList”, which is defined in the second row of the grid that define the root content of the page, it has the “ItemSelected” subscribed to ignore the “SelectItem”, the “SeparatorColor” is defined as blue and the “ItemsSource” is binding with the “Sessions” property (which is a property from the object defined in “BindingContext”.

Data bindings allow properties of two objects to be linked so that a change in one causes a change in the other. See more about it in these article Data Binding Basics and From Data Bindings to MVVM.

Each row from the ListView can be defined with static or dynamic size. In this case was defined a static size for each platform (related with screen resolution). A developer that needs to have different row’s size depending the data showed is recommended to use the property HasUnevenRows.

To complete, in code behind, you need to define the Sessions that should be an “ObservableCollection” of Session (this kind of list allow to notify the UI each time an object is removed or added in the list). You need to get the sessions from the “SessionsDataSource” and you need to define the “BindingContext”. The data should be loaded in the “OnAppearing” method and is not recommended to load it in the constructor of the page, because it will increase the time required to create the page which can create issues.

public partial class SessionsView : ContentPage
{
    public SessionsView()
    {
        InitializeComponent();
        Sessions = new ObservableCollection&lt;Session&gt;();
        BindingContext = this;

    }

    public ObservableCollection&lt;Session&gt; Sessions { get; set; }

    protected override void OnAppearing()
    {
        base.OnAppearing();
        if (Sessions.Count == 0)
        {
            var sessions = SessionsDataSource.GetSessions();
            foreach (var session in sessions)
            {
                Sessions.Add(session);
            }
        }
    }
    private void SessionsList_OnItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
        if (SessionsList.SelectedItem == null)
        {
            return;
        }

        SessionsList.SelectedItem = null;
    }
}

In this case, you will not use MVVM pattern, which is extremely recommended in real projects. To keep it simple the code behind will have the behavior used by UI that in a MVVM pattern is defined in the ViewModel.

3.4. Create the ItemTemplate

The Listview has the “ItemTemplate” property that allows defining a “DataTemplate” for each row. In this case you will define a template as described in figure 34, which code will be:

<ListView.ItemTemplate>
     <DataTemplate>
                <ViewCell>
                    <ViewCell.View>
                        <Grid BackgroundColor="Transparent" Padding="20,0,20,0">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="5" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="48" />
                                <RowDefinition Height="5" />
                            </Grid.RowDefinitions>
                            <!-- Define the Image from Speaker -->
                            <Image Grid.Row="1"
                                   HorizontalOptions="StartAndExpand"
                                   Source="{Binding Speaker.ImageUrl}"
                                   VerticalOptions="Start">
                                <Image.WidthRequest>
                                    <OnPlatform Android="50"
                                                WinPhone="100"  iOS="50"
                                                x:TypeArguments="x:Double" />
                                </Image.WidthRequest>
                                <Image.HeightRequest>
                                    <OnPlatform Android="50"
                                                WinPhone="100" iOS="50"
                                                x:TypeArguments="x:Double" />
                                </Image.HeightRequest>
                            </Image>
                            <!-- Define the Image from Speaker -->
                            <StackLayout Grid.Row="1"
                                         Grid.Column="1"
                                         HorizontalOptions="FillAndExpand"
                                         Padding="10,0,0,0">
                                <Label Font="Medium"
                                       FontAttributes="Bold"
                                       Text="{Binding Name}"
                                       TextColor="Black" />
                                <Label Font="Medium"
                                       LineBreakMode="TailTruncation"
                                       Text="{Binding Speaker.Name}"
                                       TextColor="Black" />
                                <Label Font="Small"
                                       LineBreakMode="TailTruncation"
                                       TextColor="Black" Text="{Binding Details}"/>
                            </StackLayout>               
                            <!-- Define the menu for each session -->  
                       </Grid>
                   </ViewCell.View>
                </ViewCell>
            </DataTemplate>
  </ListView.ItemTemplate>

Xamarin Workshop - Figure 34

Figure 34: A row in listview

Running the application you will have the following:

Xamarin Workshop - Figure 35

Figure 35: The Windows Phone, iOS and Android application showing sessions from 1010 ENEI

3.5. Create the menu for each Session

To create the menu for each session as described in figure 36, you need to change the ItemTemplate defined above:

Xamarin Workshop - Figure 36

Figure 36: The session’s menu

The implementation can be something as following:

<Grid Grid.Row="2" Grid.Column="0"  Grid.ColumnSpan="2" Padding="0,5,0,0">
              <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /><ColumnDefinition Width="*" />
                <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /><ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="*" />
              </Grid.ColumnDefinitions>
              <StackLayout Grid.Column="1" Orientation="Horizontal">
                <Image>
                  <Image.WidthRequest>
                    <OnPlatform Android="48" WinPhone="48" iOS="30"  x:TypeArguments="x:Double" />
                  </Image.WidthRequest>
                  <Image.HeightRequest>
                    <OnPlatform Android="48"  WinPhone="48" iOS="30" x:TypeArguments="x:Double" />
                  </Image.HeightRequest>
                  <Image.Source>
                    <OnPlatform x:TypeArguments="ImageSource">
                      <OnPlatform.iOS>  <FileImageSource File="ic_action_like.png" />
                      </OnPlatform.iOS>
                      <OnPlatform.Android> <FileImageSource File="ic_action_like.png" />
                      </OnPlatform.Android>
                      <OnPlatform.WinPhone><FileImageSource File="Images/ic_action_like.png" />
                      </OnPlatform.WinPhone>
                    </OnPlatform>
                  </Image.Source>
                </Image>
                <Label Font="Small" Text="{Binding NumLikes}" TextColor="#0094FF" VerticalOptions="Center" />
              </StackLayout>
              <Image Grid.Column="3" Source="{Binding IsFavorite, Converter={StaticResource FavoriteImageConverter}}">
                <Image.WidthRequest>
                  <OnPlatform Android="48" WinPhone="48" iOS="30"  x:TypeArguments="x:Double" />
                </Image.WidthRequest>
                <Image.HeightRequest>
                  <OnPlatform Android="48"  WinPhone="48"    iOS="30"  x:TypeArguments="x:Double" />
                </Image.HeightRequest>
              </Image>
              <Image Grid.Column="5">
                <Image.WidthRequest>
                  <OnPlatform Android="30"  WinPhone="48" iOS="30" x:TypeArguments="x:Double" />
                </Image.WidthRequest>
                <Image.HeightRequest>
                  <OnPlatform Android="30"  WinPhone="48" iOS="30" x:TypeArguments="x:Double" />
                </Image.HeightRequest>
                <Image.Source>
                  <OnPlatform x:TypeArguments="ImageSource">
                    <OnPlatform.iOS><FileImageSource File="ic_action_share_2.png" /></OnPlatform.iOS>
                    <OnPlatform.Android><FileImageSource File="ic_action_share_2.png" /></OnPlatform.Android>
                    <OnPlatform.WinPhone>
  <FileImageSource File="Images/ic_action_share_2.png" /></OnPlatform.WinPhone>
                  </OnPlatform> </Image.Source>  </Image>
              <Image Grid.Column="7">
                <Image.WidthRequest>
                  <OnPlatform Android="30" WinPhone="48" iOS="30"   x:TypeArguments="x:Double" />
                </Image.WidthRequest>
                <Image.HeightRequest>
                  <OnPlatform Android="30"   WinPhone="48"  iOS="30" x:TypeArguments="x:Double" />
                </Image.HeightRequest>
                <Image.Source>
                  <OnPlatform x:TypeArguments="ImageSource">
                    <OnPlatform.iOS>   <FileImageSource File="ic_action_list.png" />
                    </OnPlatform.iOS>
                    <OnPlatform.Android><FileImageSource File="ic_action_list.png" />
                    </OnPlatform.Android>
                    <OnPlatform.WinPhone> <FileImageSource File="Images/ic_action_list.png" />
                    </OnPlatform.WinPhone>
                  </OnPlatform>
                </Image.Source>
              </Image>
            </Grid>

The SessionDetailsView will have a similar implementation for the header as defined in SessionsView, the difference it is the title value, which will be defined by the Session’s name.

The code above contains a grid with four images: Like, Favorite, Share and Details. And for each one we need to subscribe the Tap event using the “GestureRecognizers” from the Image, this way you need to define for each image its TapGesture as following:

 <Image.GestureRecognizers>
 <TapGestureRecognizer x:Name="FavoriteGesture"
             CommandParameter="{Binding}" Tapped="FavoriteGestureRecognizer_OnTapped" />
</Image.GestureRecognizers>

In an implementation based in the MVVM pattern we use the Command instead of the Tapped event.

Where the event’s handler will be defined as following:

  private void FavoriteGestureRecognizer_OnTapped(object sender, EventArgs e)
    {
        var tappedEventArg = e as TappedEventArgs;
        if (tappedEventArg != null)
        {
            var session = tappedEventArg.Parameter as Session;
            if (session != null)
            {
                session.IsFavorite = !session.IsFavorite;
            }
        }
    }

Do the same for “Like” and for Share and Details we will see it in next steps.

The Favorite option uses a FavoriteImageConverter which allow to show the right image based if the user selected it as favorite or not, this way if the favorite option is red it means the user selected the session as favorite, the blue color is defined by default.

The implementation of the FavoriteImageConverter will be something as following:

public class FavoriteImageConverter:IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
        {
            return Device.OS == TargetPlatform.WinPhone ? "Images/ic_action_heart.png" : "ic_action_heart.png";
        }
        var isFavorite = (bool) value;

        if (isFavorite)
        {
            return Device.OS == TargetPlatform.WinPhone ? "Images/ic_action_heart_red.png" : "ic_action_heart_red.png";
        }
        return Device.OS == TargetPlatform.WinPhone ? "Images/ic_action_heart.png" : "ic_action_heart.png";
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
Running the application

At this moment you should have the UI from the 1010 ENEI Sessions App as described in figure 37:

Xamarin Workshop - Figure 37

Figure 37: The Windows Phone, iOS and Android applications

Xamarin Guide 2. Create the model and data source

Scope

This Xamarin Workshop Guide was created for the The Portuguese National Meeting of IT Students (ENEI) by Sara Silva which original content is available here. With the goal to extend it to the global community, it was published in a new project called Xam Community Workshop, which the main goal is to any developer, or user group customize it to theirs events.

Guides 2. Create the model and data source

2.1. The model

Before create the UI, you need to define the model, for it you will define:

  • Session: class that define a session from 1010 ENEI event
  • Speaker: class that define a speaker

Each session should have a speaker (In real scenarios can have more than one!). Figure 22 define the class diagram from the model:

Xamarin Workshop - Figure 22

Figure 22: The model

In ENEI.SessionsApp project create the Session and the Speaker class in a “Model” folder, as described in figures 23 and 24:

Xamarin Workshop - Figure 23

Figure 23: Creating new Folder

Xamarin Workshop - Figure 24

Figure 24: Adding new file

The Session class can be defined by:

public class Session : INotifyPropertyChanged
{
    private int _numLikes;
    private Speaker _speaker;
    private string _date;
    private string _description;
    private string _name;
    private bool _isFavorite;
    private string _schedule;
    private string _room;

    public string Name
    {
        get { return _name; }
        set { _name = value; OnPropertyChanged(); }
    }

    public string Description
    {
        get { return _description; }
        set { _description = value; OnPropertyChanged(); }
    }

    public string Date
    {
        get { return _date; }
        set { _date = value; OnPropertyChanged(); }
    }

    public int NumLikes
    {
        get { return _numLikes; }
        set { _numLikes = value; OnPropertyChanged();}
    }

    public Speaker Speaker
    {
        get { return _speaker; }
        set { _speaker = value; OnPropertyChanged(); }
    }

    public bool IsFavorite
    {
        get { return _isFavorite; }
        set { _isFavorite = value; OnPropertyChanged();}
    }

    public string Schedule
    {
        get { return _schedule; }
        set { _schedule = value; OnPropertyChanged(); }
    }

    public string Room
    {
        get { return _room; }
        set { _room = value; OnPropertyChanged(); }
    }

    public string Details
    {
        get { return string.Format("{0} | {1} | Sala {2} ", Date, Schedule, Room); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

And the Speaker class can be defined by:

public class Speaker : INotifyPropertyChanged
{
    private string _name;
    private string _imageUrl;

    public string Name
    {
        get { return _name; }
        set { _name = value; OnPropertyChanged();}
    }

    public string ImageUrl
    {
        get { return _imageUrl; }
        set { _imageUrl = value; OnPropertyChanged(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

 

Both class implements the interface INotifyPropertyChangedv, which allow notify the UI about changes in model and this way the data will be update in UI (when is used the bindings).

 

2.2. The data source

The data source will define the data that will be loaded by the application, at this moment you will have hard code data, but in real scenarios you should have a file, database or services to provide it.

Get the SessionsDataSource class here, or create your own data.

Xamarin Guide 1: Create a Xamarin Forms project

Scope

This Xamarin Workshop Guide was created for the The Portuguese National Meeting of IT Students (ENEI) by Sara Silva which original content is available here. With the goal to extend it to the global community, it was published in a new project called Xam Community Workshop, which the main goal is to any developer, or user group customize it to theirs events.

Guide 1. Create a Xamarin Forms project 

The application you will create is a Xamarin Forms application, based in Portable Class Library project.

1.1 Using Xamarin Studio in Mac

Start by opening the Xamarin Studio as described in figure 1 Xamarin Workshop - Figure 1

Figure 1: Xamarin Studio in a Mac

Then create a new Blank App (Xamarin Forms Portable), as following:

Xamarin Workshop - Figure 2

Figure 2: Creating a Blank App (Xamarin Forms Portable)

Which result will be something as described in Figure 3:

Xamarin Workshop - Figure 3

Figure 3: The ENEI.SessionsApp solution

The ENEI.SessionApp solution is defined by three projects:

  • ENEI.SessionsApp: portable class library project, which will contain the shared code between targets. This project is independent of the platform;
  • ENEI.SessionsApp.Droid: Xamarin Android project, which define the Android application and knows the Android API;
  • ENEI.SessionsApp.iOS: Xamarin iOS project, which define the iOS application and knows the iOS API;

Now, you should update the NuGet Packages available in project. In the case described in figure 4, you only need to update the Xamarin Forms NuGet Package:

Xamarin Workshop - Figure 4

Figure 4: Xamarin Forms Nuget package to update in iOS application

To update this package you only need to open the context menu, do a right click to open the context menu and then click “Update”, as described in Figure 5:

Xamarin Workshop - Figure 5

Figure 5: Updating NuGet packages

The result will be

Xamarin Workshop - Figure 6

Figure 6: iOS project updated

You need to do the same in the others projects, if needed. Before run the application, you should select the solution and define the configurations, as following:

Xamarin Workshop - Figure 7

Figure 7: Configuration Properties

Wowwww, now you are ready to create your 1010 ENEI Session app!

1.2. Using Xamarin Studio in Windows

Start by opening the Xamarin Studio as described in figure 8:

Xamarin Workshop - Figure 8

Figure 8: Xamarin Studio in Windows

Then create a new Blank App (Xamarin Forms Portable), as described in the following figure:

Xamarin Workshop - Figure 9

Figure 9: Creating a Blank App (Xamarin Forms Portable)

The result will be something as described in figure 10:

Xamarin Workshop - Figure 10

Figure 10: The ENEI.SessionsApp solution

The ENEI.SessionApp solution is defined by two projects:

  • ENEI.SessionsApp: portable class library project, which will contain the shared code between targets. This project is independent of the platform;
  • ENEI.SessionsApp.Droid: Xamarin Android project, which define the Android application and knows the Android API;

Now, you should update the NuGet Packages available in the project. In the case described in figure 11, you only need to update the Xamarin Forms NuGet Package and the Xamarin.Android.Support.v4 NuGet Package:

Xamarin Workshop - Figure 11

Figure 11: Nuget packages to update in Android application

To update this package you only need to open the context menu, doing a right click with the mouse and then click “Update”, as described in figure 12:

Xamarin Workshop - Figure 12

Figure 12: Updating Nuget packages

The result will be

Xamarin Workshop - Figure 13

Figure 13: Android project updated

You need to do the same in the other project, if needed. Wowwww, now you are ready to create your 1010 ENEI Session app!

1.3. Using Visual Studio in Windows

Start by opening the Visual Studio as described in figure 14

Xamarin Workshop - Figure 14

Figure 14: Visual Studio 2013

And then create a new Blank App (Xamarin Forms Portable), as following:

Xamarin Workshop - Figure 15

Figure 15: Creating a Blank App (Xamarin Forms Portable)

Which result will be something as described in figure 16:

Xamarin Workshop - Figure 16 Figure 16: The ENEI.SessionsApp solution

The ENEI.SessionApp solution is defined by four projects:

  • ENEI.SessionsApp: portable class library project, which will contain the shared code between targets. This project is independent of the platform;
  • ENEI.SessionsApp.Droid: Xamarin Android project, which define the Android application and knows the Android API;
  • ENEI.SessionsApp.iOS: Xamarin iOS project, which define the iOS application and knows the iOS API;
  • ENEI.SessionsApp.WinPhone: Windows Phone project, which define the Windows Phone application and knows the Windows Phone API;

Now, you should update the Nuget Packages available in the project. This case you only need to update the Xamarin Forms Nuget Package, as described in figure 17 and figure 18:

Xamarin Workshop - Figure 17

Figure 17: Opening the “Manage NuGet Package” window

Xamarin Workshop - Figure 18

Figure 18: Nuget Package Manager

The result will be

Xamarin Workshop - Figure 19

Figure 19: Xamarin Forms NuGet package updated

You need to do the same in the others project, if needed.

Before run the application, you should select the solution and define the build and deploy apps, as following: Xamarin Workshop - Figure 20

Figure 20: Configuration Properties

Wowwww you ready to create your 1010 ENEI app!

1.4. Running the application

Depending the scenario you are, you will have more or less platforms covered, here is an overview:

  • Using Xamarin Studio in a Mac: Android + iOS Apps
  • Using Xamarin Studio in Windows: Android Apps
  • Using Visual Studio without Xamarin plugin: Windows Apps
  • Using Visual Studio with Xamarin plugin: Windows, Android and iOS (*) apps.

(*) Is required a Xamarin Build Host in a Mac connect to Visual Studio.

In figure 21, is possible to see the Android, iOS and Windows Phone applications running at the same time. The Android app is running in Xamarin Android Player, iOS app is running in IPhone Simulator and Windows Phone application is running in a Lumia 1020 device (which is connect to a Windows running in a Parallels, in a Mac).

Xamarin Workshop - Figure 21

Figure 21: Android, iOS and Windows Phone applications running at same time

1.5. Additional notes – Xamarin Forms initialization

Each developer should understand how Xamarin Forms app is defined. This way, developers should know: In ENEI.SessionsApp.iOS app, more specific in AppDelegate.cs has the following code:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
            global::Xamarin.Forms.Forms.Init();
            LoadApplication(new App());

            return base.FinishedLaunching(app, options);
}

Which initialize the Xamarin Forms and define which class has the start point for the Xamarin Forms App that defines the main page created with the Xamarin Forms API. The same happens in ENEI.Sessions.Android app, more specific in MainActivity.cs:

protected override void OnCreate(Bundle bundle)
{
        base.OnCreate(bundle);
        global::Xamarin.Forms.Forms.Init(this, bundle);
        LoadApplication(new App());
}

And in ENEI.Sessions.WinPhone app, more specific in MainPage.xaml.cs

 public MainPage()
  {
        InitializeComponent();
        SupportedOrientations = SupportedPageOrientation.PortraitOrLandscape;

        global::Xamarin.Forms.Forms.Init();
        LoadApplication(new ENEI.SessionsApp.App());
 }

At this moment, the App.cs defined in ENEI.SessionsApp (portable class library) is defined by

public class App : Application
{
    public App()
    {
        // The root page of your application
        MainPage = new ContentPage
        {
            Content = new StackLayout
            {
                VerticalOptions = LayoutOptions.Center,
                Children = {
                    new Label {
                        XAlign = TextAlignment.Center,
                        Text = "Welcome to Xamarin Forms!"
                    }
                }
            }
        };
    }
 …

As mentioned early, the ENEI.SessionsApp will be the project, which will have the shared code between targets and it is independent of the platform. This way, in this project you will define the Model, the Views, the data source and other useful class that can be reused between platforms.