Palestra Xamarin – Universidade Nova de Lisboa

xamarim    As aplicações móveis estão muito na moda, e daí que tantos de nós já tenham tido N ideias para uma aplicação móvel. Também muitos programadores decerto que já se aventuraram a criar pelo menos uma app. E agora uma questão muito importante: para que plataforma desenvolveram? Android? iOS? Windows? … 3 Apps? … 3 Linguagens de programação? Nesta sessão, a Sara irá apresentar a Xamarin e os seus produtos. Irá também explicar em que consiste o desenvolvimento de aplicações cross-platform usando Xamarin, quais as boas práticas que se devem seguir e de que forma se deve reutilizar o código para que no final não acabe numa app cheia de “Spaghetti”. Aproveita esta sessão para começares a utilizar mais uma plataforma que é inteiramente grátis para estudantes!

Ver mais em: http://www.revista-programar.info/artigos/xamarin-sem-custos-para-estudantes/.

Não percas esta oportunidade, reserva já o teu lugar: http://goo.gl/PAGfQD

#PGGD27 – 27º Portugal Girl Geek Dinner – Lisboa

O próximo encontro em Lisboa vai contar com a Cláudia e a Ekaterina e vais poder aprender mais sobre OData e machine learning!

Os lugares são limitados! Inscreve-te aqui!
Agenda:

19:00 Registo / Snacks & Drinks

19:30 Boas-vindas

19:40 Ekaterina Stambolieva – What can machine learning do for businesses?

Ekaterina is very passionate and interested in machine learning and its real-world applications. She will introduce us to the machine learning world, speak about why and how companies apply it, and tell us what skills we need to develop to become machine learning experts.

20:20 Cláudia Carvalho – OData – The Protocol for REST APIs

OData is currently a standard way to create a REST API. In this session, Cláudia will introduce us to the potentials and benefits of ODATA and the simplicity behind the creation of an OData Server. Finally, we will learn more about OData queries and operations for any kind of ODATA server.

21:00 Encerramento

Como chegar ao ISCTE-IUL e ao Auditório 0NE01.

Apoio:

ISCTE-IUL ACM

PTXug – Xamarin Workshop #1

Event Details

No dia 30-05-2015 será realizada a PTXug – Xamarin Talk #1 em Lisboa. Para participar, efectue o registo de acordo com as instruções abaixo.

Agenda

14:45  – Recepção dos participantes
15:00  –  Criação de ambiente de desenvolvimento para Windows & Mac – Sara Silva
 Este Workshop será focado na criação de ambiente de desenvolvimento em Windows/Mac, detalhando as várias ferramentas e SDKs que deverão ser instalados.
17:00  –  Sorteio de Prémios
Requisitos: cada participante deverá ter conhecimentos de programação (C#, Java ou Objective-C/Swift preferencialmente) e trazer um portátil Windows ou Mac.

Local

MAIN HUB – Innovation, Incubation & Development ( junto à estação de metro Cabo Ruivo)
Avenida Pádua 10A
1800-297 Lisboa
Portugal


Patrociníos

 

PTXug – Xamarin Talks #1

Event Details

No dia 30-05-2015 será realizada a PTXug – Xamarin Talk #1 em Lisboa. Para participar, efectue o registo de acordo com as instruções abaixo.

Agenda

09:45  – Recepção dos participantes
10:00  – await Xamarin() – Paulo Morgado
11:00  – Intervalo
11:30  – WCF em desenvolvimento cross-platform usando Xamarin – João Cardoso
12:30  – Sorteio de Prémios
Nota: Ao final da reunião, escolhemos um restaurante próximo e fazemos um almoço em grupo para continuar o convívio e aproximar as pessoas. A participação é opcional.

Local

MAIN HUB – Innovation, Incubation & Development ( junto à estação de metro Cabo Ruivo)
Avenida Pádua 10A
1800-297 Lisboa
Portugal


Patrociníos

 

Xamarin Guide 11: Create a LoginView

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.

11. Create a LoginView

In this step you will learn how to create the user interface to the LoginView using the Font Awesome, how to create the LoginViewModel and how to handle the navigation between pages.

Creating the UI using Font Awesome

The Font Awesome support icons which can be displayed using a Label, this way is possible to use this font to show icon in the application. In this step you will use the Microsoft, Google and Facebook icons to display in the UI, this way you do not need to use images.

To start, open the ENEI.SessionsApp project and add a new XAML page in the Views folder, as following:

Figure 55: Creating LoginView

Figure 55: Creating LoginView

The result will be the following XAML page:

<?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.LoginView">
<Label Text="{Binding MainText}" VerticalOptions="Center" HorizontalOptions="Center" />
</ContentPage>

Now, you can define the user interface, but before it you need to do some additional tasks, in each platform to make sure the font will be displayed in the screen when you run the app. In general you need:

  • In ENEI.SessionsApp.iOS
    • Add the FontAwesome.ttf file to Resources folderFigure 56: The Resources folder

      Figure 56: The Resources folder

    • Change the Info.plist, to include the font

In Visual Studio or Xamarin Studio is possible to edit the xml as following:

 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
   <dict>

   …

   <key>UIAppFonts</key>
    <array>
    <string>FontAwesome.ttf</string>
   </array> 
</dict>
</plist>

In Xamarin Studio you can add the font as following:

Figure 57: The Source panel from Info.plist in Xamarin Studio

Figure 57: The Source panel from Info.plist in Xamarin Studio

  • In ENEI.SessionsApp.Android
    • Add the FontAwesome.ttf to the Assets folderFigure 58: The Assets folder

      Figure 58: The Assets folder

    • Create a Render for a CustomLabel
  • [assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
    namespace ENEI.SessionsApp.Droid.Renders
    {
       public class CustomLabelRenderer: LabelRenderer
       {
           protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
          {
    base.OnElementChanged(e);
    
    var label = (TextView)Control;
    Typeface font = Typeface.CreateFromAsset(Forms.Context.Assets, "FontAwesome.ttf");
    label.Typeface = font;
          }
       }
    }
  • In ENEI.SessionsApp.WinPhone and ENEI.SessionsApp.WinRT
    • Add the FontAwesome.ttf to the Assets/Fonts folderFigure 59: The Assets/Folder folder

      Figure 59: The Assets/Folder folder

    • Set the FontAwesome.ttf as Content and Copy AlwaysFigure 60: Configurations

      Figure 60: Configurations

• In ENEI.SessionsApp

  • Add a CustomLabel class
  • Define the FontFamily for each platform
  • public class CustomLabel : Label
    {
        public CustomLabel()
        {
          FontFamily = Device.OnPlatform(
           iOS: "FontAwesome", 
           Android: null,
           WinPhone:@"\Assets\Fonts\FontAwesome.ttf#FontAwesome");
    
        if (Device.OS == TargetPlatform.Windows)
        {
            FontFamily = @"\Assets\Fonts\FontAwesome.ttf#FontAwesome";
        }
       }
    }

Now you are ready to create the UI for the LoginView. The base for the page can be something 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"
         xmlns:controls="clr-namespace:ENEI.SessionsApp.Controls;assembly=ENEI.SessionsApp"
         x:Class="ENEI.SessionsApp.Views.LoginView"
         Title="Authentication" BackgroundColor="White" x:Name="ContentPage"
         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="Medium" FontAttributes="Bold"
           TextColor="Black">
            <OnPlatform Android="" WinPhone="Authentication"
                iOS="" x:TypeArguments="x:String" />
        </Label>
      </StackLayout>
  <StackLayout Spacing="20" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" Grid.Row="1"> 
           <!—login by social network will be here -->
</StackLayout>

Then you can define options for login with Facebook, Google or Microsoft as following:

  • Facebook
  • <StackLayout WidthRequest="300" HeightRequest="60" Orientation="Horizontal" BackgroundColor="#3b5998" HorizontalOptions="Center" Spacing="20">
    <controls:CustomLabel FontSize="Small"
                        HorizontalOptions="CenterAndExpand"
                        Text=""
                        TextColor="White"
                        VerticalOptions="CenterAndExpand" />
    <Label FontAttributes="Bold"
            FontSize="Small"
            HorizontalOptions="StartAndExpand"
            Text="Facebook"
            TextColor="White"
            VerticalOptions="CenterAndExpand" />
    </StackLayout>
  • Google
  • <StackLayout WidthRequest="300" HeightRequest="60"  Orientation="Horizontal" BackgroundColor="#dd4b39" HorizontalOptions="Center" Spacing="20">
      <controls:CustomLabel FontSize="Small"
                          HorizontalOptions="CenterAndExpand"
                          Text=""
                          TextColor="White"
                          VerticalOptions="CenterAndExpand" />
      <Label FontAttributes="Bold"
            FontSize="Small"
            HorizontalOptions="StartAndExpand"
            Text="Google"
            TextColor="White"
            VerticalOptions="CenterAndExpand" />
    </StackLayout>
  • Microsoft
  • <StackLayout WidthRequest="300" HeightRequest="60"  Orientation="Horizontal" BackgroundColor="#219dfd" HorizontalOptions="Center" Spacing="20">
    <controls:CustomLabel FontSize="Small"
                       HorizontalOptions="CenterAndExpand"
                       Text=""
                       TextColor="White"
                       VerticalOptions="CenterAndExpand" />
    <Label FontAttributes="Bold"
           FontSize="Small"
           HorizontalOptions="StartAndExpand"
           Text="Microsoft"
           TextColor="White"
           VerticalOptions="CenterAndExpand" />
    </StackLayout>

When you run the application the result will something as described in figure 61:

Figure 61: The LoginView

Figure 61: The LoginView

See more details about this subject in the following references: Working with Fonts and FontAwesome Library for Xamarin.iOS (MonoTouch).

Create the LoginViewModel

At this moment, you have the user interface to the LoginView, this way it is possible to define the LoginViewModel, which will have the action to each option in LoginView.

Open the ENEI.SessionsApp project and add the LoginViewModel to the ViewModels folder, as following:

Figure 62: The LoginViewModel

Figure 62: The LoginViewModel

Then create the LoginCommnad, as following:

public class LoginViewModel
{
    public LoginViewModel()
    {
        LoginCommand =new Command(DoLogin);
    }

    private void DoLogin(object param)
    {
        var option = param.ToString();
        switch (option)
        {
            case "facebook":
             //connect with facebook api
                break;
            case "goolge":
             //connect with google api
                break;
            case "microsoft":
             //connect with microsoft api
                break;
        }
    }

    public ICommand LoginCommand { get; set; }
}

In this case, you only created one ICommand that will be used be all options in the LoginView and for it is required to send as CommandParameter the name of the option, as we will see next.

Now, connect the UI with the LoginViewModel and to start, define the LoginViewModel and binding it to the BindingContext as following:

public partial class LoginView : ContentPage
{
    public LoginView()
    {
        InitializeComponent();
        BindingContext = new LoginViewModel();
    }
}

Then change the StackLayout that is the root for each option as following:

  <StackLayout WidthRequest="300" HeightRequest="60" Orientation="Horizontal" BackgroundColor="#3b5998" HorizontalOptions="Center" Spacing="20">
     <StackLayout.GestureRecognizers>
          <TapGestureRecognizer CommandParameter="facebook"
                                Command="{Binding LoginCommand}"/>
      </StackLayout.GestureRecognizers>
    <controls:CustomLabel FontSize="Small"
                        HorizontalOptions="CenterAndExpand"
                        Text=""
                        TextColor="White"
                        VerticalOptions="CenterAndExpand" />
    <Label FontAttributes="Bold"
            FontSize="Small"
            HorizontalOptions="StartAndExpand"
            Text="Facebook"
            TextColor="White"
            VerticalOptions="CenterAndExpand" />
  </StackLayout>

Do a similar implementation to the others option. When you run the application you should call the DoLogin method, as following:

Figure 63: The DoLogin method in debug mode

Figure 63: The DoLogin method in debug mode

Handle Navigation

At this moment you do not have the authentication, but you can create the complete flow to the application. This way, you need to define the navigation between pages, which is the main goal of this step.

To start, you can create a NavMessage, as following:

public class NavMessage
{
    public string Page { get; set; }

    public object Param { get; set; }
}

Then, in the App class you can use MessaginCenter to navigate between pages, as following:

    public App()
    {
        InitializeComponent();
        MainPage = new NavigationPage(new LoginView())
        {
            BarBackgroundColor = Color.White,
            BarTextColor = Color.Black,
            BackgroundColor = Color.White,
        };

        MessagingCenter.Subscribe<NavMessage>(this, "Navigation", navMessage =>
        {
            switch (navMessage.Page)
            {
                case "login":
                    MainPage = new LoginView();
                    break;
                case "sessions":
                    MainPage = new NavigationPage(new SessionsView())
                    {
                        BarBackgroundColor = Color.White,
                        BarTextColor = Color.Black,
                        BackgroundColor = Color.White,
                    };
                    break;
                case "details":
                    MainPage.Navigation.PushAsync(new SessionDetailsView(navMessage.Param as Session), true);
                    break;
            }
        });
    }

There are different way to handle the navigation and it can be defined based in the application requirements.

In the LoginViewModel you should change the DoLogin method to:

private void DoLogin(object param)
    {
        var option = param.ToString();
        switch (option)
        {
            case "facebook":
             //connect with facebook api
                break;
            case "goolge":
             //connect with google api
                break;
            case "microsoft":
             //connect with microsoft api
                break;
        }
        MessagingCenter.Send(new NavMessage{ Page = "sessions"}, "Navigation");
    }

At this moment is not important the authentication, because that feature will be focused in nexts steps.

In the SessionsViewModel change the SeeSessionDetails method to:

 

And, in the SessionsView remove the navigation, which result should be:

  public SessionsView()
  {
     InitializeComponent();
  }

At this moment if you run the application you should start in the LoginView and then you can see the SessionsView and the SessionDetailsView.

Xamarin Guide 10: Move ItemTemplate to Resources

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.

10. Move ItemTemplate to Resources

In the last two step you learned to create an App class using XAML approach and how to use MVVM pattern, to separate the UI to the logic. In this step you learn how extract the DataTemplate from the listview’s Itemtemplate to Resources.

In the App.xaml prepare the code to add the DataTemplate, for it you need to define the Application’s Resources as following:

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

   
 

And then copy the DataTemplate defined inside the ListView’s ItemTemplate:

&lt;ListView x:Name="SessionsList"
           Grid.Row="1"
           RowHeight="{Binding Converter={StaticResource RowHeightConverter}}"
           ItemSelected="SessionsList_OnItemSelected"
           ItemsSource="{Binding Sessions}"
           SeparatorColor="#0094FF"&gt;
 
   
    <!--—this DataTemplate---->
   

To inside the ResourceDictionary, as following:

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

 
  
    
      
        
         
          
            
            
          
          
            
            
            
            
          
          <img alt="" />
            
              
            
            
              
            
          
          

            <label>

            <label>
            <label>
          </label></label></label>

               ….

  
  
 

Then, define the x:key value to identify the DataTemplate as following:

 <Application.Resources>
    <ResourceDictionary>
      <DataTemplate x:Key="SessionTemplate">

If you run the application you will get some errors because it is required to move the converters and theSessionViewModel to App.xaml, as following:

  …

 
   
     <viewModels:SessionViewModel x:Key="SessionViewModel"/>
     
     
     
     
        

 ….

Now you can use the DataTemplate defined in Resources, using the key defined “SessionTemplate”, as following:

   <!-- ListView will be defined here -->
   <ListView x:Name="SessionsList"
               Grid.Row="1"
               RowHeight="{Binding Converter={StaticResource RowHeightConverter}}"
               ItemSelected="SessionsList_OnItemSelected"
               ItemsSource="{Binding Sessions}"
               SeparatorColor="#0094FF" ItemTemplate="{StaticResource SessionTemplate}">

This way, the SessionsView.xaml looks cleaner, it is easier to understand the code and is possible to reuse the DataTemplate if needed.

Xamarin Guide 9: Use MVVM pattern

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.

9. Use MVVM pattern

In this step you will learn how refactor your code to use the MVVM pattern.

“The Model-View-ViewModel (MVVM) pattern helps you to cleanly separate the business and presentation logic of your application from its user interface (UI). Maintaining a clean separation between application logic and UI helps to address numerous development and design issues and can make your application much easier to test, maintain, and evolve. It can also greatly improve code re-use opportunities and allows developers and UI designers to more easily collaborate when developing their respectiv e parts of the application.”

in MSDN

To help understand the MVVM pattern, here is a diagram which explain how it works:

MVVM Pattern diagram

Figure 53: MVVM Pattern diagram

In the Sessions App, you can create two view models, one for each page. To help matching views and view models, in general you should have:

  • SessionsView will be connected with SessionViewModel
  • SessionDetailsView will be connected with SessionDetailsViewModel

Usually all view models are defined in a ViewModels folders, this way any developers will recognize that the application uses MVVM pattern and it is easy to match Views and ViewModels (but any developer is free to organize the application based in application requirements!).

Let’s create the view models!

In ENEI.SessionsApp project, create a folder called ViewModels, and then create the class SessionViewModel. The result should be something as following:

MVVM Pattern diagram

Figure 54: The view model folder

Now you need to refactor the code in SessionView.xaml.cs. For it let’s define the SessionViewModel class as following:

public class SessionViewModel
{
    public SessionViewModel()
    {
        Sessions = new ObservableCollection(); 
    }

    public ObservableCollection Sessions { get; set; }

    public async Task LoadDataAsync()
    {
       await Task.Run(() =>
        {
            if (Sessions.Count == 0)
            {
                var sessions = SessionsDataSource.GetSessions();
                foreach (var session in sessions)
                {
                    Sessions.Add(session);
                }
            }
        });
    }
}

This way, you defined the Sessions list and the LoadDataAsync in ViewModel, now you need to create the command for each option in the menu.

In the SessionsView.xaml.cs you have the event’s handler from the Tap event (for Like, Favorite, Share and SessionDetails) which are defined in Xaml as following:

  <TapGestureRecognizer x:Name="DetailsGesture"
                    CommandParameter="{Binding}"
                    Tapped="DetailsGesture_OnTapped" />

These event’s handle are not friendly for who want implement MVVM pattern, to solve it was create the “ICommand” that allow to call the associate action. This way we need to define the ICommand for each option as following:

public ICommand LikeCommand { get; private set; }
public ICommand FavoriteCommand { get; private set; }
public ICommand ShareCommand { get; private set; }
public ICommand SessionDetailsCommand { get; private set; }

And in the constructor is required to initialize each one, as following:

 public SessionViewModel()
    {
        Sessions = new ObservableCollection();
        LikeCommand = new Command(ApplyLike);
        FavoriteCommand = new Command(ApplyFavorite);
        ShareCommand = new Command(Share);
        SessionDetailsCommand = new Command(SeeSessionDetails);
    }

Where each method above is defined by:

  • ApplyLike
  • private void ApplyLike(object param)
    {
        var session = param as Session;
        if (session != null)
        {
            session.NumLikes++;
        }
    }
  • ApplyFavorite
  • private void ApplyFavorite(object param)
    {
        var session = param as Session;
        if (session != null)
        {
            session.IsFavorite = !session.IsFavorite;
        }
    }
  • Share
  • private void Share(object param)
    {
        var session = param 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/");
            }
        }
    }
  • SeeSessionDetails
  • private void SeeSessionDetails(object param)
    {
        var session = param as Session;
        if (session != null)
        {
            MessagingCenter.Send(session, "SeeSessionDetails");
        }
    }

The MessagingCenter is a class that has the capability to send and receive message. In this case, when a user wants to see the session details the view model will send a message with the session to the view, and then the view will navigate to the SessionDetailsView.

See more about Publish and Subscribe with MessagingCenter.

At the end your SessionViewModel class should be defined as following:

public class SessionViewModel
{
    public SessionViewModel()
    {
        Sessions = new ObservableCollection();
        LikeCommand = new Command(ApplyLike);
        FavoriteCommand = new Command(ApplyFavorite);
        ShareCommand = new Command(Share);
        SessionDetailsCommand = new Command(SeeSessionDetails);
    }

    public ObservableCollection Sessions { get; set; }
    public ICommand LikeCommand { get; private set; }
    public ICommand FavoriteCommand { get; private set; }
    public ICommand ShareCommand { get; private set; }
    public ICommand SessionDetailsCommand { get; private set; }

    private void ApplyLike(object param)
    {
        var session = param as Session;
        if (session != null)
        {
            session.NumLikes++;
        }
    }

    private void ApplyFavorite(object param)
    {
        var session = param as Session;
        if (session != null)
        {
            session.IsFavorite = !session.IsFavorite;
        }
    }

    private void Share(object param)
    {
        var session = param 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/");
            }
        }
    }

    private void SeeSessionDetails(object param)
    {
        var session = param as Session;
        if (session != null)
        {
            MessagingCenter.Send(session, "SeeSessionDetails");
        }
    }

    public async Task LoadDataAsync()
    {
       await Task.Run(() =>
        {
            if (Sessions.Count == 0)
            {
                var sessions = SessionsDataSource.GetSessions();
                foreach (var session in sessions)
                {
                    Sessions.Add(session);
                }
            }
        });
    }
}

And the SessionsView.xaml.cs should be changed to:

public partial class SessionsView : ContentPage
{
    public SessionsView()
    {
        InitializeComponent();
        MessagingCenter.Subscribe(this, "SeeSessionDetails", session =>
        {
            Navigation.PushAsync(new SessionDetailsView(session), true);
        });
    }

    protected override async void OnAppearing()
    {
        base.OnAppearing();
        var viewmodel = BindingContext as SessionViewModel;
        if (viewmodel != null)
        {
            await viewmodel.LoadDataAsync();
        }
    }

    private void SessionsList_OnItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
        //workarround to clean the select item
        if (SessionsList.SelectedItem == null)
        {
            return;
        }

        SessionsList.SelectedItem = null;
    }
}

The event’s handler SessionsList_OnItemSelected will not be changed, because it is a workaround to clean the selected item.

In the SessionsView.xaml is required to do few changes:

  • Define the SessionViewModel as a resource from the page
  • <ContentPage.Resources>
       
    
  • Binding the SessionViewModel to the BindingContext from the view
  • xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:converters="clr-namespace:ENEI.SessionsApp.Converters;assembly=ENEI.SessionsApp"
         xmlns:viewModels="clr-namespace:ENEI.SessionsApp.ViewModels;assembly=ENEI.SessionsApp"
         x:Class="ENEI.SessionsApp.Views.SessionsView"
         Title="1010 ENEI || Sessões"
         BackgroundColor="White" 
         x:Name="ContentPage" 
         BindingContext="{StaticResource SessionViewModel}"
         Icon="ic_action_users.png">
  • For each option change the TapGestureRecognizer
  •  <TapGestureRecognizer 
       CommandParameter="{Binding}" 
       Command="{Binding SessionDetailsCommand, Source={StaticResource SessionViewModel}}"/>

The Command is binding to the respective command from the view model, but each developer should be aware that when the view is loaded the binding context from the Image is defined with a Session from the respective listview’s item. For this reason is required to define the binding’s Source, which uses the view model as a static resource (at this moment is not possible to apply relative binding and is not good practice to define the commands in the model object because it belong to the view model!).

If you run the application it must behave as before.

It is possible to define the view model to the SessionDetailsView, but because it only show a Session and do not have any other capability is not important that change it.

To learn more about this subject is recommend to read the following articles: XAML Basics Contents

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