XAM120 Intro to Xamarin.Forms

Exercise 2: Creating Xamarin.Forms Phoneword

The goal of this exercise is to create a new Xamarin.Forms application which displays a UI to translate an alphanumeric phone number to a numeric number and place a call. The UI will consist of a: Label, an Entry, and two Button controls.

Our steps for this exercise will be broken into two sections:

  1. Create the UI
  2. Add the behavior

When we are done, the application will look similar to the images shown below:

Screenshots of finished Phoneword exercise project running on various simulators
Finished Phoneword exercise project
To complete the exercise, you will need Visual Studio for Windows or macOS with the Xamarin development tools installed. You will also need either an emulator/simulator or a device to run the exercise on. Please see the setup page if you need help installing the Xamarin development environment.

Create the Phoneword project

Open Visual Studio and create a New Solution. This will open the New Project wizard in Visual Studio which has a few screens you need to fill in.

  1. Create a new solution. Select the Blank Forms App project type in the Multiplatform category.
  2. Name the app Phoneword.
New Project
  1. Check the Use Portable Class Library box in the Shared Code section.
    • Note: You can also choose "Use Shared Library" - generally everything here will work, and the platform-specific code could be implemented differently in that project type.
  2. Uncheck the Use XAML for user interface files checkbox. We will create the UI in code.
New Project Settings
  1. Create a new solution. Select Mobile App (Xamarin.Forms) under Visual C# > Cross-Platform.
  2. Name the app Phoneword.
New Project
  1. Select the Blank App to create an app with a XAML-based UI.
  2. Check Xamarin.Forms for the UI Technology.
  3. Select .NET Standard from the Code Sharing Strategy choice to put shared code in a compiled library.
Note: You can also choose Shared Project - generally everything here will work, and the platform-specific code could be implemented differently in that project type.
  1. Click OK to create your solution.
New Project

Add a new C# source file

  1. Right-click on the PCL project named Phoneword and select Add > New File....
  2. Select Empty File under General to add a blank C# file to the application.
  3. Name the file PhonewordTranslator.cs.
New Project
  1. Right-click on the .NET Standard project named Phoneword and select Add > Class.... (This will preselect the Visual C# > Class item template.)
  2. Name the file PhonewordTranslator.cs.
New Project

Add the translation logic

Place the following code into the new PhonewordTranslator.cs source file:

using System.Text;

namespace Core
{
    public static class PhonewordTranslator
    {
        public static string ToNumber(string raw)
        {
            if (string.IsNullOrWhiteSpace(raw))
                return null;

            raw = raw.ToUpperInvariant();

            var newNumber = new StringBuilder();
            foreach (var c in raw)
            {
                if (" -0123456789".Contains(c))
                    newNumber.Append(c);
                else
                {
                    var result = TranslateToNumber(c);
                    if (result != null)
                        newNumber.Append(result);
                    // Bad character?
                    else
                        return null;
                }
            }
            return newNumber.ToString();
        }

        static bool Contains(this string keyString, char c)
        {
            return keyString.IndexOf(c) >= 0;
        }

        static readonly string[] digits = {
            "ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ"
        };

        static int? TranslateToNumber(char c)
        {
            for (int i = 0; i < digits.Length; i++)
            {
                if (digits[i].Contains(c))
                    return 2 + i;
            }
            return null;
        }
    }
}

Examine the code:

It has a single public static method, which you will be using to translate the number from alphanumeric text into a regular numeric phone number.


Restructure the boilerplate code

Next, let's make the code a bit more maintainable by restructuring the shared code.

  1. We'll be creating our own code-based UI, so delete the existing MainPage.xaml and MainPage.xaml.cs files from the project.
  2. Create a new class in a new file named MainPage that derives from ContentPage.
  1. Create a new class in a new file named MainPage that derives from ContentPage.
using Xamarin.Forms;
...
public class MainPage : ContentPage
{
    public MainPage()
    {
        Content = new StackLayout
        {
            VerticalOptions = LayoutOptions.Center,
            Children = {
                new Label {
                    HorizontalTextAlignment = TextAlignment.Center,
                    Text = "Welcome to Xamarin.Forms!"
                }
            }
        };
    }
    ...
}
Since we created an identically named code-based initial content page, the existing code in App.xaml.cs will continue to set up our first page.
  1. Open the Application class in the shared library that was created with the project. This is the class that is responsible for presenting the initial UI. It will either be in a source file named App.xaml.cs or App.cs depending on the IDE and template you are using.
  2. In the Application class (app.cs or app.xaml.cs), change the constructor to instantiate your new MainPage class and assign it to the MainPage property.
public class App : Application
{
    public App()
    {
        // The root page of your application
        MainPage = new MainPage();
    }
    ...
}

Run the application

Run the application and verify the UI displays correctly.

Screenshot of the Phoneword project running on an iOS Simulator
Screenshot of the Phoneword project running on an Android emulator

Create the UI for Phoneword

Next, we need to describe the user interface for Phoneword. Remember, we are using controls defined in Xamarin.Forms which will then be rendered with native implementations in each project.

  1. Open MainPage.cs.
  2. Create a StackLayout.
  3. Create the required controls for the Phoneword UI:
    • A Label with the Text property set to "Enter a Phoneword:". This will prompt the user to input the phone number they would like translated.
    • An Entry that will allow the user to edit the phone number which is used to collect the input from the user. It should be initialized with the Text "1-855-XAMARIN". The user will be able to replace the initial text with their own; however, pre-populating it with a phoneword will be convenient for testing.
    • A Button that will run the logic to translate the phone number. Its Text property should be set to "Translate".
    • A second Button displaying the Text "Call", which will place the call. This Button should be initially disabled (hint: use the IsEnabled property).
    • Store the Entry and the two Button controls in class fields so you can interact with them later.
  4. Add the controls to the StackLayout.
  5. Assign the StackLayout to MainPage's Content property.
public partial class MainPage : ContentPage
{
   Entry phoneNumberText;
   Button translateButton;
   Button callButton;

   public MainPage()
   {
        this.Padding = new Thickness(20, 20, 20, 20);

        StackLayout panel = new StackLayout
        {
            Spacing = 15
        };

        panel.Children.Add(new Label {
            Text = "Enter a Phoneword:",
            FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label))
        });

        panel.Children.Add(phoneNumberText = new Entry {
            Text = "1-855-XAMARIN",
        });

        panel.Children.Add(translateButton = new Button {
            Text = "Translate"
        });

        panel.Children.Add(callButton = new Button {
            Text = "Call",
            IsEnabled = false,
        });

        this.Content = panel;
    }
}

Respond to button taps

Subscribe a handler to the Clicked event of the Translate button. Use a named method named OnTranslate that takes an object and an EventArgs as parameters.

Your handler should translate the entered value using the PhonewordTranslator.ToNumber method and store the result in a field named translatedNumber.

Here are some additional hints for the code:

public class MainPage : ContentPage
{
    ...
    string translatedNumber;

    public MainPage()
    {
        ...
        translateButton.Clicked += OnTranslate;
        this.Content = panel;
    }

    private void OnTranslate(object sender, EventArgs e)
    {
        string enteredNumber = phoneNumberText.Text;
        translatedNumber = Core.PhonewordTranslator.ToNumber(enteredNumber);

        if (!string.IsNullOrEmpty(translatedNumber))
        {
            // TODO:
        }
        else
        {
            // TODO:
        }
    }
}

Update the UI

Next, let's add some logic to change the Text of the Call Button to include the phone number when it is successfully translated. You can use the value you stored in the translatedNumber field. In addition, enable and disable the button based on the successful translation - e.g. if TranslateNumber returned null, disable the button, but if it was successful, enable it.

private void OnTranslate(object sender, EventArgs e)
{
    string enteredNumber = phoneNumberText.Text;
    translatedNumber = Core.PhonewordTranslator.ToNumber(enteredNumber);
    if (!string.IsNullOrEmpty(translatedNumber))
    {
        callButton.IsEnabled = true;
        callButton.Text = "Call " + translatedNumber;
    }
    else
    {
        callButton.IsEnabled = false;
        callButton.Text = "Call";
    }
}

Run the application

  1. Build and run the application. The application will show a disabled Call Button.
  2. Select the Translate button and verify that the Call button text changes to "Call 1-855-9262746" and the Call button is enabled.
  3. Change the phone number in the text field. On iOS the in-screen keyboard displays automatically. This behavior is built into Xamarin.Forms and makes the keyboard experience consistent across the platforms.
  4. Run the app on at least one additional platform. Notice the UI is consistant but looks appropriate for each platform while providing the same behavior.
Phoneword

Exercise summary

In this exercise, you have added a custom UI to your application using pages and views.

You can view the completed solution in the Exercise 2 > Completed folder of your copy of the cloned or downloaded course materials.

Go Back