Skip to content

Lesson3

Poh Zhi-Ee edited this page Nov 15, 2018 · 16 revisions

Table of Contents

  1. Creating a project
  2. Basic XAML
  3. Data Binding
  4. MVVM Basics

Creating a project

Go to File -> New -> New Project

Select Cross-Platform

Select Mobile App(Xamarin.Forms) image

Note: In case you cannot see Xamarin.Forms option you can go Visual Studio Installer and install .NET Mobile Development

You should see something like this in Solution Explorer.

image

It is fine if you don't have the UWP project, although it is recommended to have, because building and running UWP is fastest, but Windows only.

Basic XAML

Extensible Application Markup Language (XAML) is a declarative XML-based language developed by Microsoft that is used for initializing structured values and objects.

Read through the tutorial here: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/xaml-basics/

Tips

You can look through all the possible options when looking through Visual Studio's suggestions, as seen below. image

You can preview your UI when you are doing the design image

Examples

StackLayout

Considered a container. Able to keep adding elements, will order elements sequentially.

Example of 2 Labels inside a StackLayout

<StackLayout>
    <Label Text="Welcome to Xamarin.Forms!" 
        HorizontalOptions="Center"
        VerticalOptions="CenterAndExpand" />
    <Label Text="HELLO"
            FontSize="Large"
            HorizontalOptions="Center"
            VerticalOptions="CenterAndExpand" />
</StackLayout>

Grid

Also another container. Much more controllable than StackLayout, can adjust rows and heights based on screen size, absolute size, or child element size.

Only way to add row is to add RowDefinition, column then ColumnDefinition Example of a 3x3 Grid

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
        <RowDefinition Height="100" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="100" />
    </Grid.ColumnDefinitions>
    ...
</Grid>

Height/Width Definitions


1. Auto

Resizes based on child element in the row/column, i.e. if child element is 60px wide then the row will be 60px wide

2. *

Takes up the rest of the space in the row/column

3. <Some number>

Takes up number of pixels according to the specified number


Special case: Multiple rows/columns with *

<Grid.RowDefinitions>
    <RowDefinition Height="3*" />
    <RowDefinition Height="*" />
    <RowDefinition Height="100" />
</Grid.RowDefinitions>

In this case 100 pixels will be first allocated to the 3rd row. Then for the remaining space, 75% goes to 1st row, 25% goes to 2nd row


Assigning Child to Cell

XAML uses 0 indexing, meaning the example below is assigned to the cell in row 2 column 2.

<Entry Grid.Row="1" Grid.Column="1"
        Text="{Binding StudentId}"/>

Practice

Design something like this using grid

image

Data Binding

Data binding basically binds the UI with some data storage class, in this case normally the ViewModel. This allows us to completely separate the data from the UI. We can also separate a lot of UI logic from the UI itself, such as the function that is ran when a button is clicked.

Through this, because most of our data and logic no longer relies on the UI, we can easily swap out the UI display, and we can easily test most of our logic without a UI. With the use of automated testing, we can save a lot of time testing the UI logic.

Moreover it also makes code management simple, as the person in charge of UI styling doesn't need to care anything about where each data goes and so on.

1. Add a new class

image

Name it MainViewModel

image

2. Edit the class

i) Make the class public

ii) Add a few public properties

public class MainViewModel
{
    public string Name { get; set; }
    public string StudentId { get; set; }
    public string Email { get; set; }
}

Note: It has to be properties for the binding to work, property has the "get set" while fields don't

3. Instantiate the class

Go to MainPage.xaml.cs

In the constructor of MainPage, instantiate a MainViewModel object, and assign it to the BindingContext property

public MainPage()
{
    InitializeComponent();
    BindingContext = new MainViewModel();
}

4. Bind the property from the XAML code

<Entry Grid.Row="0" Grid.Column="1"
       Text="{Binding Name}"/>

5. Create a function to print the data

In MainViewModel.cs Add a function to print data e.g.

private void Print()
{
    Debug.WriteLine($"Name: {Name}");
    Debug.WriteLine($"StudentId: {StudentId}");
    Debug.WriteLine($"Email: {Email}");
}

6. Create a wrapper for this function

This is called a Command, can be used to bind to a button. You cannot bind a function to a button. Also in MainViewModel.cs

public ICommand ClickCommand {
    get { return new Xamarin.Forms.Command(Print); }
}

7. Bind this function to the button

<Button Text="Submit" 
        Command="{Binding ClickCommand}"/>

8. Run the application in Debug mode

For an android app that looks like this

image

Press the submit button.

Open the output window image

Data binding works now

MVVM Basics

The Model-View-ViewModel (MVVM) architectural pattern was invented with XAML in mind. The pattern enforces a separation between three software layers.

  1. the XAML user interface, called the View
  2. Underlying data model, called the Model
  3. An intermediary between the View and the Model, called the ViewModel

The View and the ViewModel are often connected through data bindings defined in the XAML file. The BindingContext for the View is usually an instance of the ViewModel

Note that there is also another very important layer, called Services. This is where most of the logic is handled, such as sending data to server or reading data from server.

In a very pure MVVM context, the ViewModel is only in charge of handling any data that directly deals with the UI, it has no responsibility on anything else, such as data processing. Moreover, in this context, it is necessary for the ViewModel to be able to run in a headless mode (i.e. without UI), such that UI logic can be tested without wasting time launching UI.

Clone this wiki locally