-
Notifications
You must be signed in to change notification settings - Fork 1
Lesson3
Go to File -> New -> New Project
Select Cross-Platform
Select Mobile App(Xamarin.Forms)
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.
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.
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/
You can look through all the possible options when looking through Visual Studio's suggestions, as seen below.
You can preview your UI when you are doing the design
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>
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>
Resizes based on child element in the row/column, i.e. if child element is 60px wide then the row will be 60px wide
Takes up the rest of the space in the row/column
Takes up number of pixels according to the specified number
<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
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}"/>
Design something like this using grid
When doing the exercise, you will find that vistual studio will actually give you some suggestion on what to auto-complete. Here is an example of what I'm talking about:
You can read up on every single of the element/property that XamarinForms provide in the XamarinForms Documentations
The documentation shows both the implementation of the UI element in XAML and C#.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0"
Grid.Column="0"
Text="Name"
Margin="5"
HorizontalTextAlignment="End"
HorizontalOptions="Center"
VerticalTextAlignment="Center" />
<Entry Grid.Row="0" Grid.Column="1"
Text="{Binding Name}"/>
<Label Grid.Row="1"
Grid.Column="0"
Text="Student ID"
Margin="5"
HorizontalTextAlignment="End"
HorizontalOptions="Center"
VerticalTextAlignment="Center" />
<Entry Grid.Row="1" Grid.Column="1"
Text="{Binding StudentId}"/>
<Label Grid.Row="2"
Grid.Column="0"
Text="Email"
Margin="5"
HorizontalTextAlignment="End"
HorizontalOptions="Center"
VerticalTextAlignment="Center" />
<Entry Grid.Row="2" Grid.Column="1"
Text="{Binding Email}" />
<Button Grid.Row="3"
Grid.Column="0"
Grid.ColumnSpan="2"
VerticalOptions="End"
Text="Submit" />
</Grid>
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.
Name it MainViewModel
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
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();
}
MainPage is a partial class because the definition of the class is split into 2 parts, 1 part in the .xaml and 1 part in the .cs file. Although they seem different and intuitively they can't combine, just know that the .xaml file will be compiled into the same intermediate language that the .cs file will be compiled into, and this is how the .xaml and .cs file is combined into 1. This also means that any variable you declare in the xaml file can be accessed in the .cs file and vice versa.
To access UI element in the .cs file, you will need to give a name/identifier to the element. In this case, the grid element is given a name/identifier of "mainGrid": .xaml part
<Grid x:Name="mainGrid">
....
</Grid>
Now you can access the grid in the .cs part also known as the Code Behind.
You can add elements directly to the grid using the name/identifier like so in the .cs part
mainGrid.Children.Add(new Label() { Text = "HELLO" });
<Entry Grid.Row="0" Grid.Column="1"
Text="{Binding Name}"/>
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}");
}
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); }
}
<Button Text="Submit"
Command="{Binding ClickCommand}"/>
For an android app that looks like this
Press the submit button.
Open the output window
Data binding works now
The Model-View-ViewModel (MVVM) architectural pattern was invented with XAML in mind. The pattern enforces a separation between three software layers.
- the XAML user interface, called the View
- Underlying data model, called the Model
- 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.