Sunteți pe pagina 1din 117

Contents

Creating Mobile Apps with Xamarin.Forms Book


1. How does Xamarin.Forms fit in?
2. Anatomy of an app
3. Deeper into text
4. Scrolling the stack
5. Dealing with sizes
6. Button clicks
7. XAML vs. code
8. Code and XAML in harmony
9. Platform-specific API calls
10. XAML markup extensions
11. The bindable infrastructure
12. Styles
13. Bitmaps
14. Absolute layout
15. The interative interface
16. Data binding
17. Mastering the Grid
18. MVVM
19. Collection views
20. Async and file I/O
21. Transforms
22. Animation
23. Triggers and behaviors
24. Page navigation
25. Page varieties
26. Custom layouts
27. Custom renderers
28. Location and maps
Creating Mobile Apps with Xamarin.Forms book
3/8/2019 • 5 minutes to read • Edit Online

Download the sample


The book Creating Mobile Apps with Xamarin.Forms by Charles Petzold is a guide for learning
how to write Xamarin.Forms applications. The only prerequisite is knowledge of the C#
programming language. The book provides an extensive exploration into the Xamarin.Forms
user interface and also covers animation, MVVM, triggers, behaviors, custom layouts, custom
renderers, and much more.
The book was published in the spring of 2016, and has not been updated since then. There is
much in the book that remains valuable, but some of the material is outdated, and some topics are no longer
entirely correct or complete.

Download eBook for free


Download your preferred eBook format from Microsoft Virtual Academy:
PDF (56Mb)
ePub (151Mb)
Kindle edition (325Mb)
You can also download individual chapters as PDF files.

Samples
The samples are available on github, and include projects for iOS, Android, and the Universal Windows Platform
(UWP ). (Xamarin.Forms no longer supports Windows 10 Mobile, but Xamarin.Forms applications will run on the
Windows 10 desktop.)

Chapter summaries
Chapter summaries are available in the chapter table show below. These summaries describe the contents of each
chapter, and include several types of links:
Links to the actual chapters of the book (at the bottom of the page), and to related articles
Links to all the samples in the xamarin-forms-book-samples GitHub repository
Links to the API documentation for more detailed descriptions of Xamarin.Forms classes, structures,
properties, enumerations, and so forth
These summaries also indicate when material in the chapter might be somewhat outdated.

Download chapters and summaries


CHAPTER COMPLETE TEX T SUMMARY

Chapter 1. How Does Xamarin.Forms Fit Download PDF Summary


In?
CHAPTER COMPLETE TEX T SUMMARY

Chapter 2. Anatomy of an App Download PDF Summary

Chapter 3. Deeper into Text Download PDF Summary

Chapter 4. Scrolling the Stack Download PDF Summary

Chapter 5. Dealing with Sizes Download PDF Summary

Chapter 6. Button Clicks Download PDF Summary

Chapter 7. XAML vs. Code Download PDF Summary

Chapter 8. Code and XAML in Harmony Download PDF Summary

Chapter 9. Platform-Specific API Calls Download PDF Summary

Chapter 10. XAML Markup Extensions Download PDF Summary

Chapter 11. The Bindable Infrastructure Download PDF Summary

Chapter 12. Styles Download PDF Summary

Chapter 13. Bitmaps Download PDF Summary

Chapter 14. Absolute Layout Download PDF Summary

Chapter 15. The Interactive Interface Download PDF Summary

Chapter 16. Data Binding Download PDF Summary

Chapter 17. Mastering the Grid Download PDF Summary

Chapter 18. MVVM Download PDF Summary

Chapter 19. Collection Views Download PDF Summary

Chapter 20. Async and File I/O Download PDF Summary

Chapter 21. Transforms Download PDF Summary

Chapter 22. Animation Download PDF Summary

Chapter 23. Triggers and Behaviors Download PDF Summary

Chapter 24. Page Navigation Download PDF Summary

Chapter 25. Page Varieties Download PDF Summary

Chapter 26. Custom Layouts Download PDF Summary


CHAPTER COMPLETE TEX T SUMMARY

Chapter 27. Custom renderers Download PDF Summary

Chapter 28. Location and Maps Download PDF Summary

Ways in which the book is outdated


Since the publication of Creating Mobile Apps with Xamarin.Forms, several new features have been added to
Xamarin.Forms. These new features are described in individual articles in the Xamarin.Forms documentation.
Other changes have caused some of the content of the book to be outdated:
.NET Standard 2.0 libraries have replaced Portable Class Libraries
A Xamarin.Forms application generally uses a library to share code among the different platforms. Originally, this
was a Portable Class Library (PCL ). There are many references to PCLs throughout the book and the chapter
summaries.
The Portable Class Library has been replaced with a .NET Standard 2.0 library, as described in the article .NET
Standard 2.0 Support in Xamarin.Forms. All the sample code from the book has been updated to use .NET
Standard 2.0 libraries.
Most of the information in the book concerning the role of the Portable Class Library remains the same for a .NET
Standard 2.0 library. One difference is that only a PCL has a numeric "profile." Also, there are some advantages to
.NET Standard 2.0 libraries. For example, Chapter 20, Async and File I/O describes how to use the underlying
platforms for performing file I/O. This is no longer necessary. The .NET Standard 2.0 library supports the familiar
System.IO classes for all Xamarin.Forms platforms.
The .NET Standard 2.0 library also allows Xamarin.Forms applications to use HttpClient to access files over the
Internet rather than WebRequest or other classes.
The role of XAML has been elevated
Creating Mobile Apps with Xamarin.Forms begins by describing how to write Xamarin.Forms applications using
C#. The Extensible Application Markup Language (XAML ) isn't introduced until Chapter 7. XAML vs. Code.
XAML now has a much larger role in Xamarin.Forms. The Xamarin.Forms solution templates distributed with
Visual Studio create XAML -based page files. A developer using Xamarin.Forms should become familiar with
XAML as early as possible. The eXtensible Application Markup Language (XAML ) section of the Xamarin.Forms
documentation contains several articles about XAML to get you started.
Supported platforms
Xamarin.Forms no longer supports Windows 8.1 and Windows Phone 8.1.
The book sometimes makes references to the Windows Runtime. This is a term that encompasses the Windows
API used in several versions of Windows and Windows Phone. More recent versions of Xamarin.Forms restricts
itself to supporting the Universal Windows Platform, which is the API for Windows 10 and Windows 10 Mobile.
A .NET Standard 2.0 library does not support any version of Windows 10 Mobile. Therefore, a Xamarin.Forms
application using a .NET Standard library will not run on a Windows 10 Mobile device. Xamarin.Forms applications
continue to run on the Windows 10 desktop, versions 10.0.16299.0 and above.
Xamarin.Forms has preview support for the Mac, WPF, GTK#, and Tizen platforms.
Chapter summaries
The chapter summaries include information concerning changes in Xamarin.Forms since the book was written.
These are often in the form of notes:
NOTE
Notes on each page indicate where Xamarin.Forms has diverged from the material presented in the book.

Samples
In the xamarin-forms-book-samples GitHub repository, the original-code-from -book branch contains
program samples consistent with the book. The master branch contains projects that have been upgraded to
remove deprecated APIs and reflect enhanced APIs. In addition, the Android projects in the master branch have
been upgraded for Android Material Design via AppCompat and will generally display black text on a white
background.

Related Links
MS Press blog
Sample code from book
Summary of Chapter 1. How does Xamarin.Forms fit
in?
1/10/2019 • 4 minutes to read • Edit Online

Download the sample

NOTE
Notes on this page indicate areas where Xamarin.Forms has diverged from the material presented in the book.

One of the most unpleasant jobs in programming is porting a code base from one platform to another, particularly
if that platform involves a different programming language. There is a temptation when porting the code to
refactor it as well, but if both platforms must be maintained in parallel, then the differences between the two code
bases will make future maintenance more difficult.

Cross-platform mobile development


This problem is common when targeting mobile platforms. Currently, there exist two major mobile platforms, the
Apple family of iPhones and iPads running the iOS operating system, and the Android operating system that runs
on a variety of phones and tablets. Another significant platform is Microsoft's Universal Windows Platform (UWP ),
which allows a single program to target both Windows 10.
A software vendor that wishes to target these platforms must deal with different user-interface paradigms, three
different development environments, three different programming interfaces, and—perhaps most awkwardly—
three different programming languages: Objective-C for the iPhone and iPad, Java for Android, and C# for
Windows.

The C# and .NET solution


Although Objective-C, Java, and C# are all derived from the C programming language, they have evolved by very
different paths. C# is the most recent of these languages and has been maturing in very useful ways. Moreover, C#
is closely associated with an entire programming infrastructure called .NET, which provides support for math,
debugging, reflection, collections, globalization, file I/O, networking, security, threading, web services, data
handling, and XML and JSON reading and writing.
Xamarin currently provides tools to target the native Mac, iOS, and Android APIs using C# and .NET. These tools
are called Xamarin.Mac, Xamarin.iOS, and Xamarin.Android, collectively known as the Xamarin platform. These are
libraries and bindings that express the native APIs of these platforms with .NET idioms.
Developers can use the Xamarin platform to write applications in C# that target Mac, iOS, or Android. But when
targeting more than one platform, it makes a lot of sense to share some of the code among the target platforms.
This involves separating the program into platform-dependent code (generally involving the user interface), and
platform-independent code, which generally requires only the base .NET framework. This platform-independent
code can either reside in a Portable Class Library (PCL ), or a shared project, often called a Shared Asset Project or
SAP.
NOTE
Portable Class Libraries have been replaced by .NET Standard libraries. All the sample code from the book has been converted
to use .NET standard libraries.

Introducing Xamarin.Forms
When targeting multiple mobile platforms, Xamarin.Forms allows even more code sharing. A single program
written for Xamarin.Forms can target these platforms:
iOS for programs that run on the iPhone, iPad, and iPod touch
Android for programs that run on Android phones and tablets
the Universal Windows Platform to target Windows 10

NOTE
Xamarin.Forms no longer supports Windows 8.1, Windows Phone 8.1, or Windows 10 Mobile, but Xamarin.Forms
applications do run on the Windows 10 desktop. There is also preview support for the Mac, WPF, GTK#, and Tizen platforms.

The bulk of a Xamarin.Forms program exists in a library or an SAP. Each of the platforms consists of a small
application stub that calls into this shared code.
The Xamarin.Forms APIs map to native controls on each platform, so that each platform maintains its characteristic
look and feel:

The screenshots from left to right show an iPhone and an Android phone:
On each screen, the page contains a Xamarin.Forms Label for displaying text, a Button for initiating actions, a
Switch for choosing an on/off value, and a Slider for specifying a value within a continuous range. All four of
those views are children of a StackLayout on a ContentPage .
Also attached to the page is a Xamarin.Forms toolbar consisting of several ToolbarItem objects. These are visible
as icons on the top of the iOS and Android screens, and on the bottom of the Windows 10 Mobile screen.
Xamarin.Forms also supports XAML, the Extensible Application Markup Language developed at Microsoft for
several application platforms. All the visuals of the program shown above are defined in XAML as demonstrated in
the PlatformVisuals sample.
A Xamarin.Forms program can determine what platform it is running on and execute different code accordingly.
More powerfully, developers can write custom code for the various platforms and run that code from a
Xamarin.Forms program in a platform-independent manner. Developers can also create additional controls by
writing renderers for each platform.
While Xamarin.Forms is a good solution for line-of-business applications, or for prototyping, or making a quick
proof-of-concept demonstration, it is less ideal for applications that require vector graphics or complex touch
interaction.

Your development environment


Your development environment depends on what platforms you want to target and what machines you want to
use.
If you want to target iOS, you will need a Mac with Xcode and the Xamarin platform installed. Supporting Android
as well requires installing Java and the required SDKs. You can then target both iOS and Android using Visual
Studio for Mac.
Installing Visual Studio allows on the PC you to target iOS, Android, and all the Windows platforms. However,
targeting iOS from Visual Studio still requires a Mac with Xcode and the Xamarin platform installed.
You can test programs on either an actual device connected by USB to the computer, or on a simulator.

Installation
Before creating and building a Xamarin.Forms application, you should try to create and build separately an iOS
application, an Android application, and a UWP application, depending on the platforms you want to target and
your development environment.
The Xamarin and Microsoft web sites contain information on how to do this:
Getting Started with iOS
Getting Started with Android
Windows Dev Center
Once you can create and run projects for these individual platforms, you should have no problem creating and
running a Xamarin.Forms application.

Related links
Chapter 1 full text (PDF )
Chapter 1 sample
Summary of Chapter 2. Anatomy of an app
3/1/2019 • 7 minutes to read • Edit Online

Download the sample

NOTE
Notes on this page indicate areas where Xamarin.Forms has diverged from the material presented in the book.

In a Xamarin.Forms application, objects that occupy space on the screen are known as visual elements,
encapsulated by the VisualElement class. Visual Elements can be split into three categories corresponding to these
classes:
Page
Layout
View
A Page derivative occupies the entire screen, or nearly the entire screen. Often, the child of a page is a Layout
derivative to organize child visual elements. The children of the Layout can be other Layout classes or View
derivatives (often called elements), which are familiar objects such as text, bitmaps, sliders, buttons, list boxes, and
so on.
This chapter demonstrates how to create an application by focusing on the Label , which is the View derivative
that displays text.

Say hello
With the Xamarin platform installed, you can create a new Xamarin.Forms solution in Visual Studio or Visual
Studio for Mac. The Hello solution uses a Portable Class Library for the common code.

NOTE
Portable Class Libraries have been replaced by .NET Standard libraries. All the sample code from the book has been converted
to use .NET standard libraries.

This sample demonstrates a Xamarin.Forms solution created in Visual Studio with no modifications. The solution
consists of six projects:
Hello, a Portable Class Library (PCL ) shared by the other projects
Hello.Droid, an application project for Android
Hello.iOS, an application project for iOS
Hello.UWP, an application project for the Universal Windows Platform (Windows 10 and Windows 10
Mobile)
Hello.Windows, an application project for Windows 8.1
Hello.WinPhone, an application project for Windows Phone 8.1
NOTE
Xamarin.Forms no longer supports Windows 8.1, Windows Phone 8.1, or Windows 10 Mobile, but Xamarin.Forms
applications do run on the Windows 10 desktop.

You can make any of these application projects the startup project, and then build and run the program on a device
or simulator.
In many of your Xamarin.Forms programs, you won't be modifying the application projects. These often remain
tiny stubs just to start up the program. Most of your focus will be the library common to all the applications.

Inside the files


The visuals displayed by the Hello program are defined in the constructor of the App class. App derives from the
Xamarin.Forms class Application .

NOTE
The Visual Studio solution templates for Xamarin.Forms create a page with a XAML file. XAML is not covered in this book
until Chapter 7.

The References section of the Hello PCL project includes the following Xamarin.Forms assemblies:
Xamarin.Forms.Core
Xamarin.Forms.Xaml
Xamarin.Forms.Platform
The References sections of the five application projects include additional assemblies that apply to the individual
platforms:
Xamarin.Forms.Platform.Android
Xamarin.Forms.Platform.iOS
Xamarin.Forms.Platform.UWP
Xamarin.Forms.Platform.WinRT
Xamarin.Forms.Platform.WinRT.Tablet
Xamarin.Forms.Platform.WinRT.Phone

NOTE
The References sections of these projects no longer list the assemblies. Instead, the project file contains a
PackageReference tags referencing the Xamarin.Forms NuGet package. The References section in Visual Studio lists the
Xamarin.Forms package rather than the Xamarin.Forms assemblies.

Each of the application projects contains a call to the static Forms.Init method in the Xamarin.Forms namespace.
This initializes the Xamarin.Forms library. A different version of Forms.Init is defined for each platform. The calls
to this method can be found in the following classes:
iOS: AppDelegate
Android: MainActivity
UWP: App class, OnLaunched method
In addition, each platform must instantiate the App class location in the shared library. This occurs in a call to
LoadApplication in the following classes:
iOS: AppDelegate
Android: MainActivity
UWP: MainPage
Otherwise, these application projects are normal "do nothing" programs.

PCL or SAP?
It's possible to create a Xamarin.Forms solution with the common code in either a Portable Class Library (PCL ) or
a Shared Asset Project (SAP ). To create an SAP solution, select the Shared option in Visual Studio. The HelloSap
solution demonstrates the SAP template with no modifications.

NOTE
Portable Class Libraries has been replaced by .NET Standard libraries. All the sample code from the book has been converted
to use .NET standard libraries. Otherwise, the PCL and .NET Standard libraries are conceptually very similar.

The library approach bundles all the common code in a library project referenced by the platform application
projects. With the SAP approach, the common code effectively exists in all the platform application projects and is
shared among them.
Most Xamarin.Forms developers prefer the library approach. In this book, most of the solutions use a library.
Those that use SAP include an Sap suffix in the project name.
With the SAP approach the code in the shared project can execute different code for the various platforms by using
C# preprocessor directives ( #if , # elif , and #endif ) with these predefined identifiers:
iOS: __IOS__
Android: __ANDROID__
UWP: WINDOWS_UWP

In a shared library, you can determine what platform you're running on at runtime, as you'll see later in this chapter.

Labels for text


The Greetings solution demonstrates how to add a new C# file to the Greetings project. This file defines a class
named GreetingsPage that derives from ContentPage . In this book, most projects contain a single ContentPage
derivative whose name is the name of the project with the suffix Page appended.
The GreetingsPageconstructor instantiates a Label view, which is the Xamarin.Forms view that displays text. The
Text property is set to the text displayed by the Label . This program sets the Label to the Content property of
ContentPage . The constructor of the App class then instantiates GreetingsPage and sets it to its MainPage
property.
The text is displayed in the upper-left corner of the page. On iOS, this means that it overlaps the page's status bar.
There are several solutions to this problem:
Solution 1. Include padding on the page
Set a Padding property on the page. Padding is of type Thickness , a structure with four properties:
Left
Top
Right
Bottom

Padding defines an area inside a page where content is excluded. This allows the Label to avoid overwriting the
iOS status bar.
Solution 2. Include padding just for iOS (SAP only)
Set a 'Padding' property only on iOS using an SAP with a C# preprocessor directive. This is demonstrated in the
GreetingsSap solution.
Solution 3. Include padding just for iOS (PCL or SAP)
In the version of Xamarin.Forms used for the book, a Padding property specific to iOS in either a PCL or SAP can
be selected using the Device.OnPlatform or Device.OnPlatform<T> static method. These methods are now
deprecated
The Device.OnPlatform methods are used to run platform-specific code or to select platform-specific values.
Internally, they make use of the Device.OS static read-only property, which returns a member of the
TargetPlatform enumeration:

iOS
Android
Windows for UWP devices.

The Device.OnPlatform methods, the Device.OS property, and the TargetPlatform enumeration are all now
deprecated. Instead, use the Device.RuntimePlatform property and compare the string return value with the
following static fields:
iOS , the string "iOS"
Android , the string "Android"
UWP , the string "UWP", referring to the Universal Windows Platform

The Device.Idiom static read-only property is related. This returns a member of the TargetIdiom , which has these
members:
Desktop
Tablet
Phone
Unsupported is unused

For iOS and Android, the cutoff between Tablet and Phone is a portrait width of 600 units. For the Windows
platform, Desktop indicates a UWP application running under Windows 10, and Phone indicates a UWP
application running under Windows 10 application.

Solution 3a. Set margin on the Label


The Margin property was introduced too late to be included in the book, but it is also of type Thickness and you
can set it on the Label to define an area outside the view that is included in the calculation of the view's layout.
The Padding property is only available on Layout and Page derivatives. The Margin property is available on all
View derivatives.

Solution 4. Center the label within the page


You can center the Label within the Page (or put it in one of eight other places) by setting the HorizontalOptions
and VerticalOptions properties of the Label to a value of type LayoutOptions . The LayoutOptions structure
defines two properties:
An Alignment property of type LayoutAlignment , an enumeration with four members: Start , which means
left or top depending on the orientation, Center , End , which means right or bottom depending on the
orientation, and Fill .
An Expands property of type bool .

Generally these properties are not used directly. Instead, combinations of these two properties are provided by
eight static read-only properties of type LayoutOptions :
LayoutOptions.Start
LayoutOptions.Center
LayoutOptions.End
LayoutOptions.Fill
LayoutOptions.StartAndExpand
LayoutOptions.CenterAndExpand
LayoutOptions.EndAndExpand
LayoutOptions.FillAndExpand

HorizontalOptions and VerticalOptions are the most important properties in Xamarin.Forms layout, and are
discussed in more detail in Chapter 4. Scrolling the Stack.
Here's the result with the HorizontalOptions and VerticalOptions properties of Label both set to
LayoutOptions.Center :

Solution 5. Center the text within the Label


You can also center the text (or place it in eight other locations on the page) by setting the HorizontalTextAlignment
and VerticalTextAlignment properties of Label to a member of the TextAlignment enumeration:
Start , meaning left or top (depending on orientation)
Center
End , meaning right or bottom (depending on orientation)

These two properties are defined only by Label , whereas the HorizontalAlignment and VerticalAlignment
properties are defined by View and inherited by all View derivatives. The visual results might seem similar, but
they are very different as the next chapter demonstrates.

Related links
Chapter 2 full text (PDF )
Chapter 2 samples
Chapter 2 F# samples
Getting Started with Xamarin.Forms
Summary of Chapter 3. Deeper into text
1/10/2019 • 6 minutes to read • Edit Online

Download the sample


This chapter explores the Label view in more depth, including color, fonts, and formatting.

Wrapping paragraphs
When the Text property of Label contains long text, Label automatically wraps it to multiple lines as
demonstrated by the Baskervilles sample. You can embed Unicode codes such as '\u2014' for the em-dash, or C#
characters like '\r' to break to a new line.
When the HorizontalOptions and VerticalOptions properties of a Label are set to LayoutOptions.Fill , the
overall size of the Label is governed by the space that its container makes available. The Label is said to be
constrained. The size of the Label is the size of its container.
When the HorizontalOptions and VerticalOptions properties are set to values other than LayoutOptions.Fill , the
size of the Label is governed by the space required to render the text, up to the size that its container makes
available for the Label . The Label is said to be unconstrained and it determines its own size.
(Note: The terms constrained and unconstrained might be counter-intuitive, because an unconstrained view is
generally smaller than a constrained view. Also, these terms are not used consistently in the early chapters of the
book.)
A view such as a Label can be constrained in one dimension and unconstrained in the other. A Label will only
wrap text on multiple lines if it is constrained horizontally.
If a Label is constrained, it might occupy considerably more space than required for the text. The text can be
positioned within the overall area of the Label . Set the HorizontalTextAlignment property to a member of the
TextAlignment enumeration ( Start , Center , or End ) to control the alignment of all the lines of the paragraph.
The default is Start and left-aligns the text.
Set the VerticalTextAlignment property to a member of the TextAlignment enumeration to position the text at the
top, center, or bottom of the area occupied by the Label .
Set the LineBreakMode property to a member of the LineBreakMode enumeration ( WordWrap , CharacterWrap ,
NoWrap , HeadTruncation , MiddleTruncation , or TailTruncation ) to control how the multiple lines in a paragraph
break or are truncated.

Text and background colors


Set the TextColor and BackgroundColor properties of Label to Color values to control the color of the text and
background.
The BackgroundColor applies to the background of the entire area occupied by the Label . Depending on the
HorizontalOptions and VerticalOptions properties, that size might be considerably larger than the area required
to display the text. You can use color to experiment with various values of HorizontalOptions , VerticalOptions ,
HorizontalExeAlignment , and VerticalTextAlignment to see how they affect the size and position of the Label , and
the size and position of the text within the Label .
The Color structure
The Color structure lets you specify colors as Red-Green-Blue (RGB ) values, or Hue-Saturation-Luminosity (HSL )
values, or with a color name. An Alpha channel is also available to indicate transparency.
Use a Color constructor to specify:
a gray shade
an RGB value
an RGB value with transparency
Arguments are double values ranging from 0 to 1.
You can also use several static methods to create Color values:
Color.FromRgb for double RGB values from 0 to 1
Color.FromRgb for integer RGB values from 0 to 255
Color.FromRgba for double RGB values with transparency
Color.FromRgba for integer RGB values with transparency
Color.FromHsla for double HSL values with transparency
Color.FromUint for a uint value calculated as ( B + 256 * ( G + 256 * ( R + 256 * A )))
Color.FromHex for a string format of hexadecimal digits in the form "#AARRGGBB" or "#RRGGBB" or
"#ARGB" or "#RGB", where each letter corresponds to a hexadecimal digit for the alpha, red, green, and blue
channels. This method is primary used for XAML color conversions as discussed in Chapter 7, XAML vs. code.
Once created, a Color value is immutable. The characteristics of the color can be obtained from the following
properties:
R
G
B
A
Hue
Saturation
Luminosity

These are all double values ranging from 0 to 1.


Coloralso defines 240 public static read-only fields for common colors. At the time the book was written, only 17
common colors were available.
Another public static read-only field defines a color with all color channels set to zero:
Color.Transparent

Several instance methods allow modifying an existing color to create a new color:
AddLuminosity
MultiplyAlpha
WithHue
WithLuminosity
WithSaturation

Finally, two static read-only properties define special color value:


Color.Default , all channels set to –1
Color.Accent

Color.Default is intended to enforce the platform's color scheme, and consequently has a different meaning in
different contexts on different platforms. By default the platform color schemes are:
iOS: Dark text on a light background
Android: Light text on a dark background (in the book) or dark text on a light background (for Material Design
via AppCompat in the master branch of the sample code repository)
UWP: Dark text on a light background
The Color.Accent value results in a platform-specific (and sometimes user-selectable) color that is visible on either
a dark or light background.

Changing the application color scheme


The various platforms have a default color scheme as shown in the list above.
When targeting Android, it's possible to switch to a dark-on-light scheme by specifying a light theme in the
Android.Manifest.xml file, or by Adding AppCompat and Material Design.
For the Windows platforms, the color theme is normally selected by the user, but you can add a RequestedTheme
attribute set to either Light or Dark in the platform's App.xaml file. By default, the App.xaml file in the UWP
project contains a RequestedTheme attribute set to Light .

Font sizes and attributes


Set the FontFamily property of Label to a string such as "Times Roman" to select a font family. However, you
need to specify a font family that is supported on the particular platform, and the platforms are inconsistent in this
regard.
Set the FontSize property of Label to a double for specifying the approximate height of the font. See Chapter 5,
Dealing with Sizes, for more details on intelligently choosing font sizes.
You can alternatively obtain one of several preset platform-dependent font sizes. The static Device.GetNamedSize
method and overload both return a double font size value appropriate to the platform based on members of the
NamedSize enumeration ( Default , Micro , Small , Medium , and Large ). The value returned from the Medium
member is not necessarily the same as Default . The NamedFontSizes sample displays text with these named
sizes.
Set the FontAttributes property of Label to a member of these FontAttributes enumeration, Bold , Italic , or
None . You can combine the Bold and Italic members with the C# bitwise OR operator.

Formatted text
In all of the examples so far, the entire text displayed by the Label has been formatted uniformly. To vary the
formatting within a text string, don't set the Text property of Label . Instead, set the FormattedText property to
an object of type FormattedString .
FormattedString has a property that is a collection of Span objects. Each Span object has its own
Spans Text ,
FontFamily , FontSize , FontAttributes , ForegroundColor , and BackgroundColor properties.

The VariableFormattedText sample demonstrates using the FormattedText property for a single line of text, and
VariableFormattedParagraph demonstrates the technique for an entire paragraph, as shown here:
The NamedFontSizes program uses a single Label and a FormattedString object to display all of the named
font sizes for each platform.

Related links
Chapter 3 full text (PDF )
Chapter 3 samples
Chapter 3 F# samples
Label
Working with Colors
Summary of Chapter 4. Scrolling the stack
12/7/2018 • 5 minutes to read • Edit Online

Download the sample


This chapter is primarily devoted to introducing the concept of layout, which is the overall term for the classes and
techniques that Xamarin.Forms uses to organize the visual display of multiple views on the page.
Layout involves several classes that derive from Layout and Layout<T> . This chapter focuses on StackLayout .

NOTE
The FlexLayout introduced in Xamarin.Forms 3.0 can be used in ways that are similar to StackLayout but with more
flexibility.

Also introduced in this chapter are the ScrollView , Frame , and BoxView classes.

Stacks of views
StackLayout derives from Layout<View> and inherits a Children property of type IList<View> . You add multiple
view items to this collection, and StackLayout displays them in a horizontal or vertical stack.
Set the Orientation property of StackLayout to a member of the StackOrientation enumeration, either Vertical
or Horizontal . The default is Vertical .
Set the Spacing property of StackLayout to a double value to specify a spacing between the children. The default
value is 6.
In code, you can add items to the Children collection of StackLayout in a for or foreach loop as demonstrated
in the ColorLoop sample, or you can initialize the Children collection with a list of the individual views as
demonstrated in ColorList. The children must derive from View but can include other StackLayout objects.

Scrolling content
If a StackLayout contains too many children to display on a page, you can put the StackLayout in a ScrollView to
allow scrolling.
Set the Content property of ScrollView to the view you want to scroll. This is often a StackLayout , but it can be
any view.
Set the Orientation property of ScrollView to a member of the ScrollOrientation property, Vertical ,
Horizontal , or Both . The default is Vertical . If the content of a ScrollView is a StackLayout , the two
orientations should be consistent.
The ReflectedColors sample demonstrates the use of ScrollView and StackLayout to display the available
colors. The sample also demonstrates how to use .NET reflection to obtain all the public static properties and fields
of the Color structure without the need to explicitly list them.

The Expands option


When a StackLayout stacks its children, each child occupies a particular slot within the total height of the
StackLayout that depends on the child's size and the settings of its HorizontalOptions and VerticalOptions
properties. These properties are assigned values of type LayoutOptions .
The LayoutOptions structure defines two properties:
Alignment of the enumeration type LayoutAlignment with four members, Start , Center , End , and Fill
Expands of type bool

For your convenience, the LayoutOptions structure also defines eight static read-only fields of type LayoutOptions
that encompass all combinations of the two instance properties:
LayoutOptions.Start
LayoutOptions.Center
LayoutOptions.End
LayoutOptions.Fill
LayoutOptions.StartAndExpand
LayoutOptions.CenterAndExpand
LayoutOptions.EndAndExpand
LayoutOptions.FillAndExpand

The following discussion involves a StackLayout with a default vertical orientation. The horizontal StackLayout is
analogous.
For a vertical StackLayout , the HorizontalOptions setting determines how a child is horizontally positioned within
the width of the StackLayout . An Alignment setting of Start , Center , or End causes the child to be horizontally
unconstrained. The child determines its own width and is positioned at the left, center, or right of the StackLayout .
The Fill option causes the child to be horizontally constrained and fills the width of the StackLayout .
For a vertical StackLayout , each child is vertically unconstrained and gets a vertical slot depending on the child's
height, in which case the VerticalOptions setting is irrelevant.
If the vertical StackLayout itself is unconstrained—that is if its VerticalOptions setting is Start , Center , or End ,
then the height of the StackLayout is the total height of its children.
However, if the vertical StackLayout is vertically constrained—if its VerticalOptions setting is Fill —then the
height of the StackLayout will be the height of its container, which might be greater than the total height of its
children. If that is the case, and if at least one child has a VerticalOptions setting with an Expands flag of true ,
then the extra space in the StackLayout is allocated equally among all those children with an Expands flag of
true . The total height of the children will then equal the height of the StackLayout , and the Alignment part of the
VerticalOptions setting determines how the child is vertically positioned in its slot.

This is demonstrated in the VerticalOptionsDemo sample.

Frame and BoxView


These two rectangular views are often used for presentation purposes.
The view displays a rectangular frame around another view, which can be a layout such as StackLayout .
Frame
Frame inherits a Content property from ContentView that you set to the view to be displayed within the Frame .
The Frame is transparent by default. Set the following three properties to customize the frame's appearance:
The OutlineColor property to make it visible. It is common to set OutlineColor to Color.Accent when you
don't know the underlying color scheme.
The HasShadow property can be set to true to display a black shadow on iOS devices.
Set the Padding property to a Thickness value to leave a space between the frame and the frame's content.
The default value is 20 units on all sides.
The Frame has default HorizontalOptions and VerticalOptions values of LayoutOptions.Fill , which means that
the Frame will fill its container. With other settings, the size of the Frame is based on the size of its content.
The Frame is demonstrated in the FramedText sample.
The BoxView displays a rectangular area of color specified by its Color property.
If the is constrained (its HorizontalOptions and VerticalOptions properties have their default settings of
BoxView
LayoutOptions.Fill ), the BoxView fills the space available for it. If the BoxView is unconstrained (with
HorizontalOptions and LayoutOptions settings of Start , Center , or End ), it has a default dimension of 40 units
square. A BoxView can be constrained in one dimension and unconstrained in the other.
Often, you'll set the WidthRequest and HeightRequest properties of BoxView to give it a specific size. This is
illustrated by the SizedBoxView sample.
You can use several instances of StackLayout to combine a BoxView and several Label instances in a Frame to
display a particular color, and then put each of these views in a StackLayout in a ScrollView to create the
attractive list of colors shown in the ColorBlocks sample:

A ScrollView in a StackLayout?
Putting a StackLayout in a ScrollView is common, but putting a ScrollView in a StackLayout is also sometimes
convenient. In theory, this shouldn't be possible because the children of a vertical StackLayout are vertically
unconstrained. But a ScrollView must be vertically constrained. It must be given a specific height so that it can
then determine the size of its child for scrolling.
The trick is to give the ScrollView child of the StackLayout a VerticalOptions setting of FillAndExpand . This is
demonstrated in the BlackCat sample.
The BlackCat sample also demonstrates how to define and access program resources that are embedded in the
shared library. This can also be achieved with Shared Asset Projects (SAPs) but the process is a little trickier, as the
BlackCatSap sample demonstrates.

Related links
Chapter 4 full text (PDF )
Chapter 4 samples
Chapter 4 F# samples
StackLayout
ScrollView
BoxView
Summary of Chapter 5. Dealing with sizes
12/7/2018 • 3 minutes to read • Edit Online

Download the sample

NOTE
Notes on this page indicate areas where Xamarin.Forms has diverged from the material presented in the book.

Several sizes in Xamarin.Forms have been encountered so far:


The height of the iOS status bar is 20
The BoxView has a default width and height of 40
The default Padding in a Frame is 20
The default Spacing on the StackLayout is 6
The Device.GetNamedSize method returns a numeric font size
These sizes are not pixels. Instead, they are device-independent units recognized independently by each platform.

Pixels, points, dps, DIPs, and DIUs


Early in the histories of the Apple Mac and Microsoft Windows, programmers worked in units of pixels. However,
the advent of higher-resolution displays required a more virtualized and abstract approach to screen coordinates.
In the Mac world, programmers worked in units of points, traditionally 1/72 inch, while Windows developers used
device-independent units (DIUs) based on 1/96 inch.
Mobile devices, however, are generally held much closer to the face and have a higher resolution than desktop
screens, which implies that a greater pixel density can be tolerated.
Programmers targeting Apple iPhone and iPad devices continue to work in units of points, but there are 160 of
these points to the inch. Depending on the device, there may be 1, 2, or 3 pixels to the point.
Android is similar. Programmers work in units of density-independent pixels (dps), and the relationship between
dps and pixels is based on 160 dps to the inch.
Windows phones and mobile devices have also established scaling factors that imply something close to 160
device-independent units to the inch.

NOTE
Xamarin.Forms no longer supports any Windows-based phone or mobile device.

In summary, a Xamarin.Forms programmer targeting phones and tablets can assume that all units of
measurement are based on the following criterion:
160 units to the inch, equivalent to
64 units to the centimeter
The read-only Width and Height properties defined by VisualElement have default "mock" values of –1. Only
when an element has been sized and accommodated in layout will these properties reflect the actual size of the
element in device-independent units. This size includes any Padding set on the element but not the Margin .
A visual element fires the SizeChanged event when its Width or Height has changed. The WhatSize sample uses
this event to display the size of the program's screen.

Metrical sizes
The MetricalBoxView uses WidthRequest and HeightRequest to display a BoxView one inch tall and one
centimeter wide.

Estimated font sizes


The FontSizes sample shows how to use the 160-units-to-the-inch rule to specify font sizes in units of points. The
visual consistency among the platforms using this technique is better than Device.GetNamedSize .

Fitting text to available size


It's possible to fit a block of text within a particular rectangle by calculating a FontSize of the Label using the
following criteria:
Line spacing is 120% of the font size (130% on the Windows platforms).
Average character width is 50% of the font size.
The EstimatedFontSize sample demonstrates this technique. This program was written before the Margin
property was available, so it uses a ContentView with a Padding setting to simulate a margin.

A fit-to-size clock
The FitToSizeClock sample demonstrates using Device.StartTimer to start a timer that periodically notifies the
application when it's time to update the clock. The font size is set to one-sixth of the page width to make the
display as large as possible.

Accessibility issues
The EstimatedFontSize program and the FitToSizeClock program both contain a subtle flaw: If the user
changes the phone's accessibility settings on Android or Windows 10 Mobile, the program no longer can estimate
how large the text is rendered based on the font size. The AccessibilityTest sample demonstrates this problem.

Empirically fitting text


Another way to fit text to a rectangle is to empirically calculate the rendered text size and adjust it up or down. The
program in the book calls GetSizeRequest on a visual element to obtain the element's desired size. That method
has been deprecated, and programs should instead call Measure .
For a Label , the first argument should be the width of the container (to allow wrapping), while the second
argument should be set to Double.PositiveInfinity to make the height unconstrained. The EmpiricalFontSize
sample demonstrates this technique.

Related links
Chapter 5 full text (PDF )
Chapter 5 samples
Chapter 5 F# samples
Summary of Chapter 6. Button clicks
12/7/2018 • 3 minutes to read • Edit Online

Download the sample


The Button is the view that allows the user to initiate a command. A Button is identified by text (and optionally an
image as demonstrated in Chapter 13, Bitmaps). Consequently, Button defines many of the same properties as
Label :

Text
FontFamily
FontSize
FontAttributes
TextColor

Button also defines three properties that govern the appearance of its border, but the support of these properties
and their mutual independence is platform specific:
BorderColor of type Color
BorderWidth of type Double
BorderRadius of type Double

Button also inherits all the properties of VisualElement and View , including BackgroundColor , HorizontalOptions ,
and VerticalOptions .

Processing the click


The Button class defines a Clicked event that is fired when the user taps the Button . The Click handler is of
type EventHandler . The first argument is the Button object generating the event; the second argument is an
EventArgs object that provides no additional information.

The ButtonLogger sample demonstrates simple Clicked handling.

Sharing button clicks


Multiple Button views can share the same Clicked handler, but the handler generally needs to determine which
Button is responsible for a particular event. One approach is to store the various Button objects as fields and
check which one is firing the event in the handler.
The TwoButtons sample demonstrates this technique. The program also demonstrates how to set the IsEnabled
property of a Button to false when pressing the Button is no longer valid. A disabled Button does not
generate a Clicked event.

Anonymous event handlers


It is possible to define Clicked handlers as anonymous lambda functions, as the ButtonLambdas sample
demonstrates. However, anonymous handlers can't be shared without some messy reflection code.

Distinguishing views with IDs


Multiple Button objects can also be distinguished by setting the StyleId property or AutomationId property to a
string . This property is defined by Element but it is not used within Xamarin.Forms. It is intended to be used
solely by application programs.
The SimplestKeypad sample uses the same event handler for all 10 number keys on a numeric keypad and
distinguishes between them with the StyleId property:

Saving transient data


Many applications need to save data when a program is terminated and to reload that data when the program
starts up again. The Application class defines several members that help your program save and restore transient
data:
The Properties property is a dictionary with string keys and object items. The contents of the dictionary
are automatically saved in application local storage prior to program termination, and reloaded when the
program starts up.
The Application class defines three protected virtual methods that the program's standard App class
overrides: OnStart , OnSleep , and OnResume . These refer to application lifecycle events.
The SavePropertiesAsync method saves the contents of the dictionary.
It is not necessary to call SavePropertiesAsync . The contents of the dictionary are automatically saved prior to
program termination and retrieved before program startup. It's useful during program testing to save data if the
program crashes.
Also useful is:
Application.Current, a static property that returns the current Application object that you can then use to
obtain the Properties dictionary.

The first step is to identify all the variables on the page that you want to persist when the program terminates. If
you know all the places where those variables change, you can simply add them to the Properties dictionary at
that point. In the page's constructor, you can set the variables from the Properties dictionary if the key exists.
A larger program will probably need to deal with application lifecycle events. The most important is the OnSleep
method. A call to this method indicates that the program has left the foreground. Perhaps the user has pressed the
Home button on the device, or displayed all the applications, or is shutting down the phone. A call to OnSleep is
the only notification that a program receives before it is terminated. The program should take this opportunity to
ensure that the Properties dictionary is up to date.
A call to OnResume indicates that the program did not terminate following the last call to OnSleep but is now
running in the foreground again. The program might use this opportunity to refresh internet connections (for
example).
A call to OnStart occurs during program startup. It is not necessary to wait until this method call to access the
Properties dictionary because the contents have already been restored when the App constructor is called.
The PersistentKeypad sample is very similar to SimplestKeypad except that the program uses the OnSleep
override to save the current keypad entry, and the page constructor to restore that data.

NOTE
Another approach to saving program settings is provided by the Xamarin.Essentials Preferences class.

Related links
Chapter 6 full text (PDF )
Chapter 6 samples
Chapter 6 F# samples
Xamarin.Forms Button
Summary of Chapter 7. XAML vs. code
12/7/2018 • 4 minutes to read • Edit Online

Download the sample

NOTE
Notes on this page indicate areas where Xamarin.Forms has diverged from the material presented in the book.

Xamarin.Forms supports an XML -based markup language called the Extensible Application Markup Language or
XAML (pronounced "zammel"). XAML provides an alternative to C# in defining the layout of the user interface of a
Xamarin.Forms application, and in defining bindings between user-interface elements and underlying data.

Properties and attributes


Xamarin.Forms classes and structures become XML elements in XAML, and properties of these classes and
structures become XML attributes. To be instantiated in XAML, a class must generally have a public parameterless
constructor. Any properties set in XAML must have public set accessors.
For properties of the basic data types ( string , double , bool , and so forth), the XAML parser uses the standard
TryParse methods to convert attribute settings to these types. The XAML parser can also easily handle
enumeration types, and it can combine enumeration members if the enumeration type is flagged with the Flags
attribute.
To assist the XAML parser, more complex types (or properties of those types) can include a
TypeConverterAttribute that identifies a class that derives from TypeConverter which supports conversion from
string values to those types. For example, the ColorTypeConverter converts color names and strings, such as
"#rrggbb", into Color values.

Property-element syntax
In XAML, classes and the objects created from them are expressed as XML elements. These are known as object
elements. Most properties of these objects are expressed as XML attributes. These are called property attributes.
Sometimes a property must be set to an object that cannot be expressed as a simple string. In such a case, XAML
supports a tag called a property element that consists of the class name and property name separated by a period.
An object element can then appear within a pair of property-element tags.

Adding a XAML page to your project


A Xamarin.Forms Portable Class Library can contain a XAML page when it is first created, or you can add a XAML
page to an existing project. In the dialog to add a new item, choose the item that refers to a XAML page, or
ContentPage and XAML. ( Not a ContentView .)

NOTE
Visual Studio options have changed since this chapter was written.

Two files are created: a XAML file with the filename extension .xaml, and a C# file with the extension .xaml.cs. The
C# file is often referred to as the code-behind of the XAML file. The code-behind file is a partial class definition
that derives from ContentPage . At build time, the XAML is parsed and another partial class definition is generated
for the same class. This generated class includes a method named InitializeComponent that is called from the
constructor of the code-behind file.
During runtime, at the conclusion of the InitializeComponent call, all the elements of the XAML file have been
instantiated and initialized just as if they had been created in C# code.
The root element in the XAML file is ContentPage . The root tag contains at least two XML namespace declarations,
one for the Xamarin.Forms elements and the other defining an x prefix for elements and attributes intrinsic to all
XAML implementations. The root tag also contains an x:Class attribute that indicates the namespace and name
of the class that derives from ContentPage . This matches the namespace and class name in the code-behind file.
The combination of XAML and code is demonstrated by the CodePlusXaml sample.

The XAML compiler


Xamarin.Forms has a XAML compiler, but its use is optional based on the use of a XamlCompilationAttribute . If the
XAML is not compiled, the XAML is parsed at build time, and the XAML file is embedded in the PCL, where it is
also parsed at runtime. If the XAML is compiled, the build process converts the XAML into a binary form, and the
runtime processing is more efficient.

Platform specificity in the XAML file


In XAML, the OnPlatform class can be used to select platform-dependent markup. This is a generic class and must
be instantiated with an x:TypeArguments attribute that matches the target type. The OnIdiom class is similar but
used much less often.
The use of OnPlatform has changed since the book was published. It was originally used in conjunction with
properties named iOS , Android , and WinPhone . It is now used with child On objects. Set the Platform property
to a string consistent with the public const fields of the Device class. Set the Value property to a value
consistent with the x:TypeArguments attribute of the OnPlatform tag.
OnPlatform is demonstrated in the ScaryColorList sample, so called because it contains blocks of nearly identical
XAML. The existence of this repetitious markup suggests that techniques should be available to reduce it.

The content property attributes


Some property elements occur quite frequently, such as the <ContentPage.Content> tag on the root element of a
ContentPage , or the <StackLayout.Children> tag that encloses the children of StackLayout .

Every class is allowed to identify one property with a ContentPropertyAttribute on the class. For this property, the
property-element tags are not required. ContentPage defines its content property as Content , and Layout<T> (the
class from which StackLayout derives) defines its content property as Children . These property element tags are
not required.
The property element of Label is Text .

Formatted text
The TextVariations sample contains several examples of setting the Text and FormattedText properties of
Label . In XAML, Span objects appear as children of the FormattedString object.

When a multiline string is set to the Text property, end-of-line characters are converted to space characters, but
the end-of-line characters are preserved when a multiline string appears as content of the Label or Label.Text
tags:

Related links
Chapter 7 full text (PDF )
Chapter 7 samples
Chapter 7 F# sample
XAML Basics
Summary of Chapter 8. Code and XAML in harmony
12/7/2018 • 2 minutes to read • Edit Online

Download the sample


This chapter explores XAML more deeply, and particularly how code and XAML interact.

Passing arguments
In the general case, a class instantiated in XAML must have a public parameterless constructor; the resultant object
is initialized through property settings. However, there are two other ways that objects can be instantiated and
initialized.
Although these are general-purpose techniques, they are mostly used in connection with MVVM View Models.
Constructors with arguments
The ParameteredConstructorDemo sample demonstrates how to use the x:Arguments tag to specify constructor
arguments. These arguments must be delimited by element tags indicating the type of the argument. For the basic
.NET data types, the following tags are available:
x:Object
x:Boolean
x:Byte
x:Int16
x:Int32
x:Int64
x:Single
x:Double
x:Decimal
x:Char
x:String
x:TimeSpan
x:Array
x:DateTime

Can I call methods from XAML?


The FactoryMethodDemo sample demonstrates how to use the x:FactoryMethod element to specify a factory
method that is invoked to create an object. Such a factory method must be public and static, and it must create an
object of the type in which it is defined. (For example the Color.FromRgb method qualifies because it is public and
static and returns a value of type Color .) The arguments to the factory method are specified within x:Arguments
tags.

The x:Name attribute


The x:Name attribute allows an object instantiated in XAML to be given a name. The rules for these names are the
same as for C# variable names. Following the return of the InitializeComponent call in the constructor, the code-
behind file can refer to these names to access the corresponding XAML element. The names are actually converted
by the XAML parser into private fields in the generated partial class.
The XamlClock sample demonstrates the use of x:Name to allow the code-behind file to keep two Label
elements defined in XAML updated with the current date and time.
The same name cannot be used for multiple elements on the same page. This is a particular problem if you use
OnPlatform to create parallel named objects for each platform. The PlatformSpecificLabele sample
demonstrates a better way to do something like that.

Custom XAML-based views


There are several ways to avoid repetition of markup in XAML. One common technique is to create a new XAML -
based class that derives from ContentView . This technique is demonstrated in the ColorViewList sample. The
ColorView class derives from ContentView to display a particular color and its name, while the ColorViewListPage
class derives from ContentPage as usual and explicitly creates 17 instances of ColorView .
Accessing the ColorView class in XAML requires another XML namespace declaration, commonly named local
for classes in the same assembly.

Events and handlers


Events can be assigned to event handlers in XAML, but the event handler itself must be implemented in the code-
behind file. The XamlKeypad demonstrates how to build a keypad user interface in XAML and how to implement
the Clicked handlers in the code-behind file.

Tap gestures
Any Viewobject can obtain touch input and generate events from that input. The View class defines a
GestureRecognizers collection property that can contain one or more instances of classes that derive from
GestureRecognizer .

The TapGestureRecognizer generates Tapped events. The MonkeyTap program demonstrates how to attach
TapGestureRecognizer objects to four BoxView elements to create an imitation game:

But the MonkeyTap program really needs sound. (See the next chapter.)

Related links
Chapter 8 full text (PDF )
Chapter 8 samples
Chapter 8 F# sample
Passing Arguments in XAML
Summary of Chapter 9. Platform-specific API calls
12/7/2018 • 2 minutes to read • Edit Online

Download the sample

NOTE
Notes on this page indicate areas where Xamarin.Forms has diverged from the material presented in the book.

It is sometimes necessary to run some code that varies by platform. This chapter explores the techniques.

Preprocessing in the Shared Asset Project


A Xamarin.Forms Shared Asset Project can execute different code for each platform using the C# preprocessor
directives #if , #elif , and endif . This is demonstrated in PlatInfoSap1:

However, the resultant code can be ugly and difficult to read.

Parallel classes in the Shared Asset Project


A more structured approach to executing platform-specific code in the SAP is demonstrated in the PlatInfoSap2
sample. Each of the platform projects contains an identically named class and methods, but implemented for that
particular platform. The SAP then simply instantiates the class and calls the method.

DependencyService and the Portable Class Library


NOTE
Portable Class Libraries have been replaced by .NET Standard libraries. All the sample code from the book has been
converted to use .NET standard libraries.

A library cannot normally access classes in application projects. This restriction seems to prevent the technique
shown in PlatInfoSap2 from being used in a library. However, Xamarin.Forms contains a class named
DependencyService that uses .NET reflection to access public classes in the application project from the library.

The library must define an interface with the members it needs to use in each platform. Then, each of the
platforms contains an implementation of that interface. The class that implements the interface must be identified
with a DependencyAttribute on the assembly level.
The library then uses the generic Get method of DependencyService to obtain an instance of the platform class
that implements the interface.
This is demonstrated in the DisplayPlatformInfo sample.

Platform-specific sound generation


The MonkeyTapWithSound sample adds beeps to the MonkeyTap program by accessing sound-generation
facilities in each platform.

Related links
Chapter 9 full text (PDF )
Chapter 9 samples
Dependency Service
Summary of Chapter 10. XAML markup extensions
3/8/2019 • 3 minutes to read • Edit Online

Download the sample


Normally, the XAML parser converts any string set as an attribute value to the type of the property based on
standard conversions for the basic .NET data types, or a TypeConverter derivative attached to the property or its
type with a TypeConverterAttribute .
But it's sometimes convenient to set an attribute from a different source, for example, an item in a dictionary, or the
value of a static property or field, or from a calculation of some sort.
This is the job of a XAML markup extension. Despite the name, XAML markup extensions are not an extension to
XML. XAML is always legal XML.

The code infrastructure


A XAML markup extension is a class that implements the IMarkupExtension interface. Such a class often has the
word Extension at the end of its name but usually appears in XAML without that suffix.
The following XAML markup extensions are supported by all implementations of XAML:
x:Static supported by StaticExtension
x:Reference supported by ReferenceExtension
x:Type supported by TypeExtension
x:Null supported by NullExtension
x:Array supported by ArrayExtension

These four XAML markup extensions are supported by many implementations of XAML, including Xamarin.Forms:
StaticResource supported by StaticResourceExtension
DynamicResource supported by DynamicResourceExtension
Binding supported by BindingExtension —discussed in Chapter 16. Data binding
TemplateBinding supported by TemplateBindingExtension —not covered in the book

An additional XAML markup extension is included in Xamarin.Forms in connection with RelativeLayout :


ConstraintExpression —not covered in the book

Accessing static members


Use the x:Static element to set an attribute to the value of a public static property, field, or enumeration member.
Set the Member property to the static member. It's usually easier to specify x:Static and the member name in
curly braces. The name of the Member property does not need to be included, just the member itself. This common
syntax is shown in the SharedStatics sample. The static fields themselves are defined in the AppConstants class.
This technique allows you to establish constants used through a program.
With an additional XML namespace declaration, you can reference public static properties, fields, or enumeration
members defined in the .NET framework, as demonstrated in the SystemStatics sample.

Resource dictionaries
The VisualElement class defines a property named Resources that you can set to an object of type
ResourceDictionary . Within XAML, you can store items in this dictionary and identify them with the x:Key
attribute. The items stored in the resource dictionary are shared among all references to the item.
StaticResource for most purposes
In most cases you'll use the StaticResource markup extension to reference an item from the resource dictionary, as
demonstrated by the ResourceSharing sample. You can use a StaticResourceExtension element or
StaticResource within curly braces:

Do not confuse the x:Static markup extension and the StaticResource markup extension.
A tree of dictionaries
When the XAML parser encounters a StaticResource , it begins searching up the visual tree for a matching key, and
then looks in the ResourceDictionary in the application's App class. This allows items in a resource dictionary
deeper in the visual tree to override a resource dictionary higher in the visual tree. This is demonstrated in the
ResourceTrees sample.
DynamicResource for special purposes
The StaticResource markup extension causes an item to be retrieved from the dictionary when a visual tree is built
during the InitializeComponent call. An alternative to StaticResource is DynamicResource , which maintains a link
to the dictionary key and updates the target when the item referenced by the key changes.
The difference between StaticResource and DynamicResource is demonstrated in the DynamicVsStatic sample.
A property set by DynamicResource must be backed by a bindable property as discussed in Chapter 11, The
bindable infrastructure.

Lesser-used markup extensions


Use the x:Null markup extension to set a property to null .
Use the x:Type markup extension to set a property to a .NET Type object.
Use x:Array to define an array. Specify the type of the array members by setting the [ Type ] property to an
x:Type markup extension.

A custom markup extension


You can create your own XAML markup extensions by writing a class that implements the IMarkupExtension
interface with a ProvideValue method.
The HslColorExtension class satisfies those requirement. It creates a value of type Color based on values of
properties named H , S , L , and A . This class is the first item in a Xamarin.Forms library named
Xamarin.FormsBook.Toolkit that is built up and used over the course of this book.
The CustomExtensionDemo sample demonstrates how to reference this library and use the custom markup
extension.

Related links
Chapter 10 full text (PDF )
Chapter 10 samples
XAML Markup Extensions
Summary of Chapter 11. The Bindable infrastructure
12/7/2018 • 4 minutes to read • Edit Online

Download the sample


Every C# programmer is familiar with C# properties. Properties contain a set accessor and/or a get accessor. They
are often called CLR properties for the Common Language Runtime.
Xamarin.Forms defines an enhanced property definition called a bindable property encapsulated by the
BindableProperty class and supported by the BindableObject class. These classes are related but quite distinct:
The BindableProperty is used to define the property itself; BindableObject is like object in that it is a base class
for classes that define bindable properties.

The Xamarin.Forms class hierarchy


The ClassHierarchy sample uses reflection to display a class hierarchy of Xamarin.Forms and demonstrate the
crucial role played by BindableObject in this hierarchy. BindableObject derives from Object and is the parent
class to Element from which VisualElement derives. This is the parent class to Page and View , which is the
parent class to Layout :

A peek into BindableObject and BindableProperty


In the classes that derive from BindableObject many CLR properties are said to be "backed by" bindable
properties. For example, the Text property of the Label class is a CLR property, but the Label class also defines
a public static read-only field named TextProperty of type BindableProperty .
An application can set or get the Text property of Label normally, or the application can set the Text by calling
the SetValue method defined by BindableObject with a Label.TextProperty argument. Similarly, an application
can obtain the value of the Text property by calling the GetValue method, again with a Label.TextProperty
argument. This is demonstrated by the PropertySettings sample.
Indeed, the Text CLR property is entirely implemented using the SetValue and GetValue methods defined by
BindableObject in conjunction with the Label.TextProperty static property.
BindableObject and BindableProperty provide support for:
Giving properties default values
Storing their current values
Providing mechanisms for validating property values
Maintaining consistency among related properties in a single class
Responding to property changes
Triggering notifications when a property is about to change or has changed
Supporting data binding
Supporting styles
Supporting dynamic resources
Whenever a property that is backed by a bindable property changes, BindableObject fires a PropertyChanged
event identifying the property that has changed. This event is not fired when the property is set to the same value.
Some properties are not backed by bindable properties, and some Xamarin.Forms classes — such as Span — do
not derive from BindableObject . Only a class that derives from BindableObject can support bindable properties
because BindableObject defines the SetValue and GetValue methods.
Because Span does not derive from BindableObject , none of its properties — such as Text — are backed by a
bindable property. This is why a DynamicResource setting on the Text property of Span raises an exception in the
DynamicVsStatic sample in the previous chapter. The DynamicVsStaticCode sample demonstrates how to set a
dynamic resources in code using the SetDynamicResource method defined by Element . The first argument is an
object of type BindableProperty .
Similarly, the SetBinding method defined by BindableObject has a first argument of type BindableProperty .

Defining bindable properties


You can define your own bindable properties using the static BindableProperty.Create method to create a static
read-only field of type BindableProperty .
This is demonstrated in the AltLabel class in the Xamarin.FormsBook.Toolkit library. The class derives from
Label and lets you specify a font size in points. It is demonstrated in the PointSizedText sample.

Four arguments of the BindableProperty.Create method are required:


propertyName : the text name of the property (the same as the CLR property name)
returnType : the type of the CLR property
declaringType : the type of the class declaring the property
defaultValue : the property's default value

Because defaultValue is of type object , the compiler must be able to determine the default value's type. For
example, if the returnType is double , the defaultValue should be set to something like 0.0 rather than just 0, or
the type mismatch will trigger an exception at runtime.
It is also very common for a bindable property to include:
propertyChanged : a static method called when the property changes value. The first argument is the instance of
the class whose property has been changed.
The other arguments to BindableProperty.Create are not as common:
defaultBindingMode : used in connection with data binding (as discussed in Chapter 16. Data binding)
validateValue : a callback to check for a valid value
propertyChanging : a callback to indicate when the property is about to change
coerceValue : a callback to coerce a set value to another value
defaultValueCreate : a callback to create a default value that cannot be shared among instances of the class (for
example, a collection)
The read-only bindable property
A bindable property can be read-only. Creating a read-only bindable property requires calling the static method
BindableProperty.CreateReadOnly to define a private static read-only field of type BindablePropertyKey .

Then, define the CLR property set accesor as private to call a SetValue overload with the BindablePropertyKey
object. This prevents the property from being set outside the class.
This is demonstrated in the CountedLabel class used in the BaskervillesCount sample.

Related links
Chapter 11 full text (PDF )
Chapter 11 samples
Bindable Properties
Summary of Chapter 12. Styles
5/20/2019 • 4 minutes to read • Edit Online

Download the sample


In Xamarin.Forms, styles allow multiple views to share a collection of property settings. This reduces markup and
enables maintaining consistent visual themes.
Styles are almost always defined and consumed in markup. An object of type Style is instantiated in a resource
dictionary and then set to the Style property of a visual element using a StaticResource or DynamicResource
markup extension.

The basic Style


A Style requires that its TargetType be set to the type of the visual object it applies to. When a Style is
instantiated in a resource dictionary (as is common) it also requires an x:Key attribute.
The Style has a content property of type Setters , which is a collection of Setter objects. Each Setter
associates a Property with a Value .
In XAML the Property setting is the name of a CLR property (such as the Text property of Button ) but the
styled property must be backed by a bindable property. Also, the property must be defined in the class indicated by
the TargetType setting, or inherited by that class.
You can specify the Value setting using the property element <Setter.Value> . This lets you set Value to an object
that can't be expressed in a text string, or to an OnPlatform object, or to an object instantiated using x:Arguments
or x:FactoryMethod . The Value property can also be set with a StaticResource expression to another item in the
dictionary.
The BasicStyle program demonstrates the basic syntax and shows how to reference the Style with a
StaticResource markup extension:

The Style object and any object created in the Style object as a Value setting are shared among all views
referencing that Style . The Style cannot contain anything that cannot be shared, such as a View derivative.
Event handlers cannot be set in a Style . The GestureRecognizers property cannot be set in a Style because it is
not backed by a bindable property.

Styles in code
Although it's not common, you can instantiate and initialize Style objects in code. This is demonstrated by the
BasicStyleCode sample.

Style inheritance
Style has a BasedOn property that you can set to a StaticResource markup extension referencing another style.
This allows styles to inherit from previous styles, and add or replace property settings. The StyleInheritance
sample demonstrates this.
If Style2 is based on Style1 , the TargetType of Style2 must be the same as Style1 or derived from Style1 .
The resource dictionary in which Style1 is stored must be the same resource dictionary as Style2 or a resource
dictionary higher in the visual tree.

Implicit styles
If a Style in a resource dictionary does not have an x:Key attribute setting, it is assigned a dictionary key
automatically, and the Style object becomes an implicit style. A view without a Style setting and whose type
matches the TargetType exactly will find that style, as the ImplicitStyle sample demonstrates.
An implicit style can derive from a Style with an x:Key setting but not the other way around. You cannot
explicitly reference an implicit style.
You can implement three types of hierarchy with styles and BasedOn :
From styles defined on the Application and Page down to styles defined on layouts lower in the visual tree.
From styles defined for base classes such as VisualElement and View to styles defined for specific classes.
From styles with explicit dictionary keys to implicit styles.
These hierarchies are demonstrated in the StyleHierarchy sample.

Dynamic styles
A style in a resource dictionary can be referenced by DynamicResource rather than StaticResource . This makes the
style a dynamic style. If that style is replaced in the resource dictionary by another style with the same key, the
views referencing that style with DynamicResource automatically change. Also, the absence of a dictionary entry
with the specified key will cause StaticResource to raise an exception but not DynamicResource .
You can use this technique to dynamically change styling or themes as the DynamicStyles sample demonstrates.
However, you cannot set the BasedOn property to a DynamicResource makeup extension because BasedOn isn't
backed by a bindable property. To derive a style dynamically, do not set BasedOn . Instead, set the BaseResourceKey
property to the dictionary key of the style you want to derive from. The DynamicStylesInheritance sample
demonstrates this technique.

Device styles
The Device.Styles nested class defines twelve static read-only fields for six styles with a TargetType of Label that
you can use for common types of text usages.
Six of these fields are of type Style that you can set directly to a Style property in code:
BodyStyle
TitleStyle
SubtitleStyle
CaptionStyle
ListItemTextStyle
ListItemDetailTextStyle

The other six fields are of type string and can be used as dictionary keys for dynamic styles:
BodyStyleKey equal to "BodyStyle"
TitleStyleKey equal to "TitleStyle"
SubtitleStyleKey equal to "SubtitleStyle"
CaptionStyleKey equal to "CaptionStyle"
ListItemTextStyleKey equal to "ListItemTextStyle"
ListItemDetailTextStyleKey equal to "ListItemDetailTextStyle"

These styles are illustrated by the DeviceStylesList sample.

Related links
Chapter 12 full text (PDF )
Chapter 12 samples
Styles
Summary of Chapter 13. Bitmaps
12/7/2018 • 9 minutes to read • Edit Online

Download the sample

NOTE
Notes on this page indicate areas where Xamarin.Forms has diverged from the material presented in the book.

The Xamarin.Forms Image element displays a bitmap. All the Xamarin.Forms platforms support the JPEG, PNG,
GIF, and BMP file formats.
Bitmaps in Xamarin.Forms come from four places:
Over the web as specified by a URL
Embedded as a resource in the shared library
Embedded as a resource in the platform application projects
From anywhere that can be referenced by a .NET Stream object, including MemoryStream

Bitmap resources in the shared library are platform-independent, while bitmap resources in the platform projects
are platform-specific.

NOTE
The text of the book makes references to Portable Class Libraries, which have been replaced by .NET Standard libraries. All
the sample code from the book has been converted to use .NET standard libraries.

The bitmap is specified by setting the Source property of Image to an object of type ImageSource , an abstract
class with three derivatives:
UriImageSource for accessing a bitmap over the web based on a Uri object set to its Uri property
FileImageSource for accessing a bitmap stored in a platform application project based on a folder and file path
set to its File property
StreamImageSource for loading a bitmap using a .NET Stream object specified by returning a Stream from a
Func set to its Stream property

Alternatively (and more commonly) you can use the following static methods of the ImageSource class, all of which
return ImageSource objects:
ImageSource.FromUri for accessing a bitmap over the web based on a Uri object
ImageSource.FromResource for accessing a bitmap stored as an embedded resource in the application PCL;
ImageSource.FromResource or ImageSource.FromResource to access a bitmap in another source assembly
ImageSource.FromFile for accessing a bitmap from a platform application project
ImageSource.FromStream for loading a bitmap based on a Stream object

There is no class equivalent of the Image.FromResource methods. The UriImageSource class is useful if you need to
control caching. The FileImageSource class is useful in XAML. StreamImageSource is useful for the asynchronous
loading of Stream objects, whereas ImageSource.FromStream is synchronous.
Platform-independent Bitmaps
The WebBitmapCode project loads a bitmap over the web using ImageSource.FromUri . The Image element is set
to the Content property of the ContentPage , so it is constrained to the size of the page. Regardless of the bitmap's
size, a constrained Image element is stretched to the size of its container, and the bitmap is displayed in its
maximum size within the Image element while maintaining the bitmap's aspect ratio. Areas of the Image beyond
the bitmap can be colored with BackgroundColor .
The WebBitmapXaml sample is similar but simply sets the Source property to the URL. The conversion is
handled by the ImageSourceConverter class.
Fit and fill
You can control how the bitmap is stretched by setting the Aspect property of the Image to one of the following
members of the Aspect enumeration:
AspectFit : respects aspect ratio (default)
Fill : fills area, does not respect aspect ratio
AspectFill : fills area but respects aspect ratio, accomplished by cropping part of the bitmap

Embedded resources
You can add a bitmap file to a PCL, or to a folder in the PCL. Give it a Build Action of EmbeddedResource. The
ResourceBitmapCode sample demonstrates how to use ImageSource.FromResource to load the file. The resource
name passed to the method consists of the assembly name, followed by a dot, followed by the optional folder
name and a dot, followed by the filename.
The program sets the VerticalOptions and HorizontalOptions properties of the Image to LayoutOptions.Center ,
which makes the Image element unconstrained. The Image and the bitmap are the same size:
On iOS and Android, the Image is the pixel size of the bitmap. There is a one-to-one mapping between bitmap
pixels and screen pixels.
On Universal Windows Platform, the Image is the pixel size of the bitmap in device-independent units. On
most devices, each bitmap pixel occupies multiple screen pixels.
The StackedBitmap sample puts an Image in a vertical StackLayout in XAML. A markup extension named
ImageResourceExtension helps to reference the embedded resource in XAML. This class only loads resources from
the assembly in which it's located, so it can't be placed in a library.
More on sizing
It's often desirable to size bitmaps consistently among all the platforms. Experimenting with StackedBitmap, you
can set a WidthRequest on the Image element in a vertical StackLayout to make the size consistent among the
platforms, but you can only reduce the size using this technique.
You can also set the HeightRequest to make the image sizes consistent on the platforms, but the constrained width
of the bitmap will limit the versatility of this technique. For an image in a vertical StackLayout , HeightRequest
should be avoided.
The best approach is to begin with a bitmap wider than the phone width in device-independent units and set
WidthRequest to a desired width in device-independent units. This is demonstrated in the DeviceIndBitmapSize
sample.
The MadTeaParty displays Chapter 7 of Lewis Carroll's Alice's Adventures in Wonderland with the original
illustrations by John Tenniel:
Browsing and waiting
The ImageBrowser sample allows the user to browse through stock images stored on the Xamarin web site. It
uses the .NET WebRequest class to download a JSON file with the list of bitmaps.

NOTE
Xamarin.Forms programs should use HttpClient rather than WebRequest for accessing files over the internet.

The program uses an ActivityIndicator to indicate that something's going on. As each bitmap is loading, the
read-only IsLoading property of Image is true . The IsLoading property is backed by a bindable property, so a
PropertyChanged event is fired when that property changes. The program attaches a handler to this event, and
uses the current setting of IsLoaded to set the IsRunning property of the ActivityIndicator .

Streaming bitmaps
The ImageSource.FromStream method creates an ImageSource based on a .NET Stream . The method must be
passed a Func object that returns a Stream object.
Accessing the streams
The BitmapStreams sample demonstrates how to use the ImaageSource.FromStream method to load a bitmap
stored as an embedded resource, and to load a bitmap across the web.
Generating bitmaps at run time
All the Xamarin.Forms platforms support the uncompressed BMP file format, which is easy to construct in code
and then store in a MemoryStream . This technique allows algorithmically creating bitmaps at runtime, as
implemented in the BmpMaker class in the Xamrin.FormsBook.Toolkit library.
The "Do It Yourself" DiyGradientBitmap sample demonstrates the use of BmpMaker to create a bitmap with a
gradient image.

Platform-specific bitmaps
All the Xamarin.Forms platforms allow storing bitmaps in the platform application assemblies. When retrieved by
a Xamarin.Forms application, these platform bitmaps are of type FileImageSource . You use them for:
the Icon property of MenuItem
the Icon property of ToolbarItem
the Image property of Button

The platform assemblies already contain bitmaps for icons and splash screens:
In the iOS project, in the Resources folder
In the Android project, in subfolders of the Resources folder
In the Windows projects, in the Assets folder (although the Windows platforms do not restrict bitmaps to that
folder)
The PlatformBitmaps sample uses code to display an icon from the platform application projects.
Bitmap resolutions
All the platforms allow storing multiple versions of bitmap images for different device resolutions. At runtime, the
proper version is loaded based on the device resolution of the screen.
On iOS, these bitmaps are differentiated by a suffix on the filename:
No suffix for 160 DPI devices (1 pixel to the device-independent unit)
'@2x' suffix for 320 DPI devices (2 pixels to the DIU )
'@3x' suffix for 480 DPI devices (3 pixels to the DIU )
A bitmap intended to be displayed as one-inch square would exist in three versions:
MyImage.jpg at 160 pixels square
MyImage@2x.jpg at 320 pixels square
MyImage@3x.jpg at 480 pixels square
The program would refer to this bitmap as MyImage.jpg, but the proper version is retrieved at runtime based on
the resolution of the screen. When unconstrained, the bitmap will always render at 160 device-independent units.
For Android, bitmaps are stored in various subfolders of the Resources folder:
drawable-ldpi (low DPI) for 120 DPI devices (0.75 pixels to the DIU )
drawable-mdpi (medium) for 160 DPI devices (1 pixel to the DIU )
drawable-hdpi (high) for 240 DPI devices (1.5 pixels to the DIU )
drawable-xhdpi (extra high) for 320 DPI devices (2 pixels to the DIU )
drawable-xxhdpi (extra extra high) for 480 DPI devices (3 pixels to the DIU )
drawable-xxxhdpi (three extra highs) for 640 DPI devices (4 pixels to the DIU )
For a bitmap intended to be rendered at one square inch, the various versions of the bitmap will have the same
name but a different size, and be stored in these folders:
drawable-ldpi/MyImage.jpg at 120 pixels square
drawable-mdpi/MyImage.jpg at 160 pixels square
drawable-hdpi/MyImage.jpg at 240 pixels square
drawable-xhdpi/MyImage.jpg at 320 pixels square
drawable-xxhdpi/MyImage.jpg at 480 pixels square
drawable-xxxhdpi/MyImage.jpg at 640 pixels square
The bitmap will always render at 160 device-independent units. (The standard Xamarin.Forms solution template
only includes the hdpi, xhdpi, and xxhdpi folders.)
The UWP project supports a bitmap naming scheme that consists of a scaling factor in pixels per device-
independent unit as a percentage, for example:
MyImage.scale-200.jpg at 320 pixels square
Only some percentages are valid. The sample programs for this book include only images with scale-200 suffixes,
but current Xamarin.Forms solution templates include scale-100, scale-125, scale-150, and scale-400.
When adding bitmaps to the platform projects, the Build Action should be:
iOS: BundleResource
Android: AndroidResource
UWP: Content
The ImageTap sample creates two button-like objects consisting of Image elements with a TapGestureRecognizer
installed. It is intended that the objects be one-inch square. The Source property of Image is set using
OnPlatform and On objects to reference potentially different filenames on the platforms. The bitmap images
include numbers indicating their pixel size, so you can see which size bitmap is retrieved and rendered.
Toolbars and their icons
One of the primary uses of platform-specific bitmaps is the Xamarin.Forms toolbar, which is constructed by adding
ToolbarItem objects to the ToolbarItems collection defined by Page . ToobarItem derives from MenuItem from
which it inherits some properties.
The most important ToolbarItem properties are:
Text for text that might appear depending on platform and Order
Icon of type FileImageSource for the image that might appear depending on platform and Order
Order of type ToolbarItemOrder , an enumeration with three members, Default , Primary , and Secondary .

The number of Primary items should be limited to three or four. You should include a Text setting for all items.
For most platforms, only the Primary items require an Icon but Windows 8.1 requires an Icon for all items. The
icons should be 32 device-independent units square. The FileImageSource type indicates that they are platform-
specific.
The ToolbarItem fires a Clicked event when tapped, much like a Button . ToolbarItem also supports Command
and CommandParameter properties often used in connection with MVVM. ( See Chapter 18, MVVM ).

Both iOS and Android require that a page that displays a toolbar be a NavigationPage or a page navigated to by a
NavigationPage . The ToolbarDemo program sets the MainPage property of its App class to the NavigationPage
constructor with a ContentPage argument, and demonstrates the construction and event handler of a toolbar.
Button images
You can also use platform-specific bitmaps to set the Image property of Button to a bitmap of 32 device-
independent units square, as demonstrated by the ButtonImage sample.

NOTE
The use of images on buttons has been enhanced. See Using bitmaps with buttons.

Related links
Chapter 13 full text (PDF )
Chapter 13 samples
Working with Images
Using bitmaps with buttons
Summary of Chapter 14. Absolute layout
4/2/2019 • 5 minutes to read • Edit Online

Download the sample


Like StackLayout , AbsoluteLayout derives from Layout<View> and inherits a Children property. AbsoluteLayout
implements a layout system that requires the programmer to specify the positions of its children and, optionally,
their size. The position is specified by the upper-left corner of the child relative to the upper-left corner of the
AbsoluteLayout in device-independent units. AbsoluteLayout also implements a proportional positioning and
sizing feature.
AbsoluteLayout should be regarded as a special-purpose layout system to be used only when the programmer can
impose a size on the children (for example, BoxView elements) or when the element's size doesn't affect the
positioning of other children. The HorizontalOptions and VerticalOptions properties have no effect on children of
an AbsoluteLayout .
This chapter also introduces the important feature of attached bindable properties that allow properties defined in
one class (in this case AbsoluteLayout ) to be attached to another class (a child of the AbsoluteLayout ).

AbsoluteLayout in code
You can add a child to the Children collection of an AbsoluteLayout using the standard Add method, but
AbsoluteLayout also provides an extended Add method that lets you specify a Rectangle . Another Add method
requires only a Point , in which case the child is unconstrained and sizes itself.
You can create a Rectangle value with a constructor that requires four values — the first two indicating the
position of the upper-left corner of the child relative to its parent, and the second two indicating the child's size. Or
you can use a constructor that requires a Point and a Size value.
These Add methods are demonstrated in AbsoluteDemo, which positions BoxView elements using Rectangle
values, and a Label element using just a Point value.
The ChessboardFixed sample uses 32 BoxView elements to create the chessboard pattern. The program gives the
BoxView elements a hard-coded size of 35 units square. The AbsoluteLayout has its HorizontalOptions and
VerticalOptions set to LayoutOptions.Center , which causes the AbsoluteLayout to have a total size of 280 units
square.

Attached bindable properties


It is also possible to set the position and, optionally, the size of a child of an AbsoluteLayout after it has been added
to the Children collection using the static method AbsoluteLayout.SetLayoutBounds . The first argument is the child;
the second is a Rectangle object. You can specify that the child sizes itself horizontally and/or vertically by setting
width and height values to the AbsoluteLayout.AutoSize constant.
The ChessboardDynamic sample puts the AbsoluteLayout in a ContentView with a SizeChanged handler to call
AbsoluteLayout.SetLayoutBounds on all the children to make them as large as possible.

The attached bindable property that AbsoluteLayout defines is the static read-only field of type BindableProperty
named AbsoluteLayout.LayoutBoundsProperty . The static AbsoluteLayout.SetLayoutBounds method is implemented
by calling SetValue on the child with the AbsoluteLayout.LayoutBoundsProperty . The child contains a dictionary in
which the attached bindable property and its value are stored. During layout, the AbsoluteLayout can obtain that
value by calling AbsoluteLayout.GetLayoutBounds , which is implemented with a GetValue call.

Proportional sizing and positioning


AbsoluteLayout implements a proportional sizing and positioning feature. The class defines a second attached
bindable property, LayoutFlagsProperty , with the related static methods AbsoluteLayout.SetLayoutFlags and
AbsoluteLayout.GetLayoutFlags .

The argument to AbsoluteLayout.SetLayoutFlags and the return value of AbsoluteLayout.GetLayoutFlags is a value


of type AbsoluteLayoutFlags , an enumeration with the following members:
None (equal to 0)
XProportional (1 )
YProportional (2 )
PositionProportional (3 )
WidthProportional (4 )
HeightProportional (8 )
SizeProportional (12 )
All (\xFFFFFFFF )

You can combine these with the C# bitwise OR operator.


With these flags set, certain properties of the Rectangle layout bounds structure used to position and size the
child are interpreted proportionally.
When the WidthProportional flag is set, a Width value of 1 means that the child is the same width as the
AbsoluteLayout . A similar approach is used for the height.

The proportional positioning takes the size into account. When the XProportional flag is set, the X property of
the Rectangle layout bounds is proportional. A value of 0 means that the child's left edge is positioned at the left
edge of the AbsoluteLayout , but a position of 1 means that the child's right edge is positioned at the right edge of
the AbsoluteLayout , not beyond the right edge of the AbsoluteLayout as you might expect. An X property of 0.5
centers the child horizontally in the AbsoluteLayout .
The ChessboardProportional sample demonstrates the use of proportional sizing and positioning.

Working with proportional coordinates


Sometimes, it's easier to think of proportional positioning differently than how it's implemented in the
AbsoluteLayout . You might prefer to work with proportional coordinates where an X property of 1 positions the
child's left edge (rather than the right edge) against the right edge of the AbsoluteLayout .
This alternative positioning scheme can be called "fractional child coordinates." You can convert from fractional
child coordinates to the layout bounds required for AbsoluteLayout using the following formulas:
layoutBounds.X = (fractionalChildCoordinate.X / (1 - layoutBounds.Width))
layoutBounds.Y = (fractionalChildCoordinate.Y / (1 - layoutBounds.Height))
The ProportionalCoordinateCalc sample demonstrates this.

AbsoluteLayout and XAML


You can use an AbsoluteLayout in XAML and set the attached bindable properties on the children of an
AbsoluteLayout using attribute values of AbsoluteLayout.LayoutBounds and AbsoluteLayout.LayoutFlags . This is
demonstrated in the AbsoluteXamlDemo and the ChessboardXaml samples. The latter program contains 32
BoxView elements but uses an implicit Style that includes the AbsoluteLayout.LayoutFlags property to keep the
markup down to a minimum.
An attribute in XAML that consists of a class name, a dot, and a property name is always an attached bindable
property.

Overlays
You can use AbsoluteLayout to construct an overlay, which covers the page with other controls, perhaps to protect
the user from interacting with the normal controls on the page.
The SimpleOverlay sample demonstrates this technique, and also demonstrates the ProgressBar , which displays
the extent to which a program has completed a task.

Some fun
The DotMatrixClock sample displays the current time with a simulated 5x7 dot matrix display. Each dot is a
BoxView (there are 228 of them ) sized and positioned on the AbsoluteLayout .

The BouncingText program animates two Label objects to bounce horizontally and vertically across the screen.

Related links
Chapter 14 full text (PDF )
Chapter 14 samples
AbsoluteLayout
Attached Properties
Summary of Chapter 15. The interactive interface
4/2/2019 • 7 minutes to read • Edit Online

Download the sample


This chapter explores eight View derivatives that allow interaction with the user.

View overview
Xamarin.Forms contains 20 instantiable classes that derive from View but not Layout . Six of these have been
covered in previous chapters:
Label : Chapter 2. Anatomy of an app
BoxView : Chapter 3. Scrolling the stack
Button : Chapter 6. Button clicks
Image : Chapter 13. Bitmaps
ActivityIndicator : Chapter 13. Bitmaps
ProgressBar : Chapter 14. AbsoluteLayout

The eight views in this chapter effectively allow the user to interact with basic .NET data types:

DATA TYPE VIEWS

Double Slider , Stepper

Boolean Switch

String Entry , Editor , SearchBar

DateTime DatePicker , TimePicker

You can think of these views as visual interactive representations of the underlying data types. This concept is
explored more in the next chapter, Chapter 16. Data binding.
The remaining six views are covered in the following chapters:
WebView : Chapter 16. Data binding
Picker : Chapter 19. Collection views
ListView : Chapter 19. Collection views
TableView : Chapter 19. Collection views
Map : Chapter 28. Location and Maps
OpenGLView : Not covered in this book (and no support for Windows platforms)

Slider and stepper


Both Slider and Stepper allow the user to choose a numeric value from a range. The Slider is a continuous
range while the Stepper involves discrete values.
Slider basics
The Slider is a horizontal bar representing a range of values from a minimum on the left to a maximum on the
right. It defines three public properties:
Value of type double , default value of 0
Minimum of type double , default value of 0
Maximum of type double , default value of 1

The bindable properties that back these properties ensure that they are consistent:
For all three properties, the coerceValue method specified for the bindable property ensures that Value is
between Minimum and Maximum .
The validateValue method on MinimumProperty returns false if Minimum is being set to a value greater than
or equal to Maximum , and similar for MaximumProperty . Returning false from the validateValue method causes
an ArgumentException to be raised.
Slider fires the ValueChanged event with a ValueChangedEventArgs argument when the Value property changes,
either programmatically or when the user manipulates the Slider .
The SliderDemo sample demonstrates the simple use of the Slider .
Common pitfalls
Both in code and in XAML, the Minimum and Maximum properties are set in the order that you specify. Be sure to
initialize these properties so that Maximum is always greater than Minimum . Otherwise an exception will be raised.
Initializing the Slider properties can cause the Value property to change and the ValueChanged event to be fired.
You should ensure that the Slider event handler doesn't access views that haven't yet been created during page
initialization.
The ValueChanged event doesn't fire during Slider initialization unless the Value property changes. You can call
the ValueChanged handler directly from code.
Slider color selection
The RgbSliders program contains three Slider elements that allow you to interactively select a color by
specifying its RGB values:

The TextFade sample uses two Slider elements to move two Label elements across an AbsoluteLayout and
fade one into the other.
The Stepper difference
The Stepper defines the same properties and events as Slider but the Maximum property is initialized to 100 and
Stepper defines a fourth property:
Increment of type double , initialized to 1

Visually, the Stepper consists of two buttons labeled – and +. Pressing – decreases Value by Increment to a
minimum of Minimum . Pressing + increases Value by Increment to a maximum of Maximum .

This is demonstrated by the StepperDemo sample.

Switch and CheckBox


The Switch allows the user to specify a Boolean value.
Switch basics
Visually, the Switch consists of a toggle that can be turned off and on. The class defines one property:
IsToggled of type bool

Switch defines one event:


Toggled accompanied by a ToggledEventArgs object, fired when the IsToggled property changes.

The SwitchDemo program demonstrates the Switch .


A traditional CheckBox
Some developers might prefer a more traditional CheckBox to the Switch . The Xamarin.FormsBook.Toolkit
library contains a CheckBox class that derives from ContentView . CheckBox is implemented by the CheckBox.xaml
and CheckBox.xaml.cs files. CheckBox defines three properties ( Text , FontSize , and IsChecked ) and a
CheckedChanged event.

The CheckBoxDemo sample demonstrates this CheckBox .

Typing text
Xamarin.Forms defines three views that let the user enter and edit text:
Entry for a single line of text
Editor for multiple lines of text
SearchBar for a single line of text for search purposes.

Entry and Editor derive from InputView , which derives from View . SearchBar derives directly from View .
Keyboard and focus
On phones and tablets without physical keyboards, the Entry , Editor , and SearchBar elements all cause a virtual
keyboard to pop up. The presence of this keyboard on the screen is related to input focus. A view must have both
its IsVisible and IsEnabled properties set to true to get input focus.
Two methods, one read-only property, and two events are involved with input focus. These are all defined by
VisualElement :

The Focus method attempts to set input focus to an element and returns true if successful
The Unfocus method removes input focus from an element
The IsFocused read-only property indicates if the element has input focus
The Focused event indicates when an element gets input focus
The Unfocused event indicates when an element loses input focus
Choosing the Keyboard
The InputView class from which Entry and Editor derive defines only one property:
Keyboard of type Keyboard

This indicates the type of keyboard that is displayed. Some keyboards are optimized for URIs or numbers.
The class allows defining a keyboard with a static
Keyboard Keyboard.Create method with an argument of type
KeyboardFlags , an enumeration with the following bit flags:

None set to 0
CapitalizeSentence set to 1
Spellcheck set to 2
Suggestions set to 4
All set to \xFFFFFFFF

When using the multiline Editor when a paragraph or more of text is expected, calling Keyboard.Create is a good
approach to selecting a keyboard. For the single-line Entry , the following static read-only properties of Keyboard
are useful:
Default
Text
Chat
Url
Email
Telephone
Numeric for positive numbers with or without a decimal point.

The KeyboardTypeConverter allows specifying these properties in XAML as demonstrated by the EntryKeyboards
program.
Entry properties and events
The single-line Entry defines the following properties:
Text of type string , the text that appears in the Entry
TextColor of type Color
FontFamily of type string
FontSize of type double
FontAttributes of type FontAttributes
IsPassword of type bool , which causes characters to be masked
Placeholder of type string , for dimly colored text that appears in the Entry before anything is typed
PlaceholderColor of type Color

The Entry also defines two events:


TextChanged with a TextChangedEventArgs object, fired whenever the Text property changes
Completed , fired when the user is finished and the keyboard is dismissed. The user indicates completion in a
platform-specific manner
The QuadraticEquations sample demonstrates these two events.
The Editor difference
The multiline Editor defines the same Text and Font properties as Entry but not the other properties. Editor
also defines the same two properties as Entry .
JustNotes is a free-form notes-taking program that saves and restores the contents of the Editor .
The SearchBar
The SearchBar does not derive from InputView , so it does not have a Keyboard property. But it does have all the
Text , Font , and Placeholder properties that Entry defines. In addition, SearchBar defines three additional
properties:
CancelButtonColor of type Color
SearchCommand of type ICommand for use with data-bindings and MVVM
SearchCommandParameter of type Object , for use with SearchCommand

The platform-specific cancel button erases the text. The SearchBar also has a platform-specific search button.
Pressing either of those buttons raises one of the two events that SearchBar defines:
TextChanged accompanied by a TextChangedEventArgs object
SearchButtonPressed

The SearchBarDemo sample demonstrates the SearchBar .

Date and time selection


The DatePicker and TimePicker views implement platform-specific controls that allow the user to specify a date
or time.
The DatePicker
DatePicker defines four properties:

MinimumDate of type DateTime, initialized to January 1, 1900


MaximumDate of typeDateTime , initialized to December 31, 2100
Date of type DateTime , initialized to DateTime.Today
Format of type string , the .NET formatting string initialized to "d", the short date pattern, resulting in a date
display like "7/20/1969" in the US.
You can set the DateTime properties in XAML by expressing the properties as property elements and using the
culture-invariant short-date format ("7/20/1969").
The DaysBetweenDates sample calculates the number of days between two dates selected by the user.
The TimePicker (or is it a TimeSpanPicker?)
TimePicker defines two properties and no events:

Time is of type TimeSpan rather than DateTime , indicating the time elapsed since midnight
Format of type string , the .NET formatting string initialized to "t", the short time pattern, resulting in a time
display like "1:45 PM" in the US.
The SetTimer program demonstrates how to use the TimePicker to specify a time for a timer. The program only
works if you keep it in the foreground.
SetTimer also demonstrates using the DisplayAlert method of Page to display an alert box.

Related links
Chapter 15 full text (PDF )
Chapter 15 samples
Slider
Entry
Editor
DatePicker
Summary of Chapter 16. Data binding
12/7/2018 • 6 minutes to read • Edit Online

Download the sample

NOTE
Notes on this page indicate areas where Xamarin.Forms has diverged from the material presented in the book.

Programmers often find themselves writing event handlers that detect when a property of one object has
changed, and use that to change the value of a property in another object. This process can be automated with the
technique of data binding. Data bindings are usually defined in XAML and become part of the definition of the
user interface.
Very often, these data bindings connect user-interface objects to underlying data. This is a technique that is
explored more in Chapter 18. MVVM. However, data bindings can also connect two or more user-interface
elements. Most of the early examples of data binding in this chapter demonstrate this technique.

Binding basics
Several properties, methods, and classes are involved in data binding:
The Binding class derives from BindingBase and encapsulates many characteristics of a data binding
The BindingContext property is defined by the BindableObject class
The SetBinding method is also defined by the BindableObject class
The BindableObjectExtensions class defines three additional SetBinding methods

The following two classes support XAML markup extensions for bindings:
BindingExtension supports the Binding markup extension
ReferenceExtension supports the x:Reference markup extension

Two interfaces are involved in data binding:


INotifyPropertyChanged in the System.ComponentModel namespace is for implementing notification when a
property changes
IValueConverter is used to define small classes that convert values from one type to another in data bindings

A data binding connects two properties of the same object, or (more commonly) two different objects. These two
properties are referred to as the source and the target. Generally, a change in the source property causes a change
to occur in the target property, but sometimes the direction is reversed. Regardless:
the target property must be backed by a BindableProperty
the source property generally is a member of a class that implements INotifyPropertyChanged

A class that implements INotifyPropertyChanged fires a PropertyChanged event when a property changes value.
BindableObject implements INotifyPropertyChanged and automatically fires a PropertyChanged event when a
property backed by a BindableProperty changes values, but you can write your own classes that implement
INotifyPropertyChanged without deriving from BindableObject .
Code and XAML
The OpacityBindingCode sample demonstrates how to set a data binding in code:
The source is the Value property of a Slider
The target is the Opacity property of a Label
The two objects are connected by setting the BindingContext of the Label object to the Slider object. The two
properties are connected by calling a SetBinding extension method on the Label referencing the
OpacityProperty bindable property and the Value property of the Slider expressed as a string.

Manipulating the Slider then causes the Label to fade in and out of view.
The OpacityBindingXaml is the same program with the data binding set in XAML. The BindingContext of the
Label is set to an x:Reference markup extension referencing the Slider , and the Opacity property of the
Label is set to the Binding markup extension with its Path property referencing the Value property of the
Slider .

Source and BindingContext


The BindingSourceCode sample shows an alternative approach in code. A Binding object is created by setting
the Source property to the Slider object and the Path property to "Value". The SetBinding method of
BindableObject is then called on the Label object.

The Binding constructor could also have been used to define the Binding object.
The BindingSourceXaml sample shows the comparable technique in XAML. The Opacity property of the
Label is set to a Binding markup extension with Path set to the Value property and Source set to an
embedded x:Reference markup extension.
In summary, there are two ways to reference the binding source object:
Through the BindingContext property of the target
Through the Source property of the Binding object itself

If both are specified, the second takes precedence. The advantage of the BindingContext is that it is propagated
through the visual tree. This is very handy if multiple target properties are bound to the same source object.
The WebViewDemo program demonstrates this technique with the WebView element. Two Button elements for
navigating backwards and forwards inherit a BindingContext from their parent that references the WebView . The
IsEnabled properties of the two buttons then have simple Binding markup extensions that target the button
IsEnabled properties based on the settings of the CanGoBack and CanGoForward read-only properties of the
WebView .

The binding mode


Set the Mode property of Binding to a member of the BindingMode enumeration:
OneWayso that changes in the source property affect the target
OneWayToSource so that changes in the target property affect the source
TwoWay so that changes in the source and target affect each other
Default to use the DefaultBindingMode specified when the target BindableProperty was created. If none was
specified, the default is OneWay for normal bindable properties, and OneWayToSource for read-only bindable
properties.
NOTE
The BindingMode enumeration now also includes OnTime for applying a binding only when the binding context changes
and not when the source property changes.

Properties that are likely to be the targets of data bindings in MVVM scenarios generally have a
DefaultBindingMode of TwoWay . These are:

Value property of Slider and Stepper


IsToggled property of Switch
Text property of Entry , Editor , and SearchBar
Date property of DatePicker
Time property of TimePicker

The BindingModes sample demonstrates the four binding modes with a data binding where the target is the
FontSize property of a Label and the source is the Value property of a Slider . This allows each Slider to
control the font size of the corresponding Label . But the Slider elements are not initialized because the
DefaultBindingMode of the FontSize property is OneWay .

The ReverseBinding sample sets the bindings on the Value property of the Slider referencing the FontSize
property of each Label . This appears to be backwards, but it works better in initialzing the Slider elements
because the Value property of the Slider has a DefaultBindingMode of TwoWay .

This is analogous to how bindings are defined in MVVM, and you'll use this type of binding frequently.

String formatting
When the target property is of type string , you can use the StringFormat property defined by BindingBase to
convert the source to a string . Set the StringFormat property to a .NET formatting string that you would use
with the static String.Format format to display the object. When using this formatting string within a markup
extension, surround it with single quotation marks so the curly braces won't be mistaken for an embedded
markup extension.
The ShowViewValues sample demonstrates how to use StringFormat in XAML.
The WhatSizeBindings sample demonstrates displaying the size of the page with bindings to the Width and
Height properties of the ContentPage .
Why is it called "Path"?
The Path property of Binding is so called because it can be a series of properties and indexers separated by
periods. The BindingPathDemos sample shows several examples.

Binding value converters


When the source and target properties of a binding are different types, you can convert between the types using a
binding converter. This is a class that implements the IValueConverter interface and contains two methods:
Convert to convert the source to the target, and ConvertBack to convert the target to the source.

The IntToBoolConverter class in the Xamarin.FormsBook.Toolkit library is an example for converting an int
to a bool . It is demonstrated by the ButtonEnabler sample, which only enables the Button if at least one
character has been typed into an Entry .
The BoolToStringConverter class converts a bool to a string and defines two properties to specify what text
should be returned for false and true values. The BoolToColorConverter is similar. The SwitchText sample
demonstrates using these two converters to display different texts in different colors based on a Switch setting.
The generic BoolToObjectConverter can replace the BoolToStringConverter and BoolToColorConverter and serve
as a generalized bool -to-object converter of any type.

Bindings and custom views


You can simplify custom controls using data bindings. The NewCheckBox.cs code file defines Text , TextColor ,
FontSize , FontAttributes , and IsChecked properties, but has no logic at all for the visuals of the control. Instead
the NewCheckBox.cs.xaml file contains all the markup for the control's visuals through data bindings on the Label
elements based on the properties defined in the code-behind file.
The NewCheckBoxDemo sample demonstrates the NewCheckBox custom control.

Related links
Chapter 16 full text (PDF )
Chapter 16 samples
Data Binding
Summary of Chapter 17. Mastering the Grid
4/2/2019 • 3 minutes to read • Edit Online

Download the sample


The Grid is a powerful layout mechanism that arranges its children into rows and columns of cells. Unlike the
similar HTML table element, the Grid is solely for purposes of layout rather than presentation.

The basic Grid


Grid derives from Layout<View> , which defines a Children property that Grid inherits. You can fill this collection
in either XAML or code.
The Grid in XAML
The definition of a Grid in XAML generally begins with filling the RowDefinitions and ColumnDefinitions
collections of the Grid with RowDefinition and ColumnDefinition objects. This is how you establish the number of
rows and columns of the Grid , and their properties.
RowDefinition has a Height property and ColumnDefinition has a Width property, both of type GridLength ,a
structure.
In XAML, the GridLengthTypeConverter converts simple text strings into GridLength values. Behind the scenes, the
GridLength constructor creates the GridLength value based on a number and a value of type GridUnitType , an
enumeration with three members:
Absolute — the width or height is specified in device-independent units (a number in XAML )
Auto — the height or width is autosized based on cell contents ("Auto" in XAML )
Star — leftover height or width is allocated proportionally (a number with "*", called star, in XAML )

Each child of the Grid must also be assigned a row and column (either explicitly or implicitly). Row spans and
column spans are optional. These are all specified using attached bindable properties — properties that are defined
by the Grid but set on children of the Grid . Grid defines four static attached bindable properties:
RowProperty — the zero-based row; default is 0
ColumnProperty — the zero-based column; default is 0
RowSpanProperty — the number of rows the child spans; default is 1
ColumnSpanProperty — the number of columns the child spans; default is 1

In code, a program can use eight static methods to set and get these values:
Grid.SetRow and Grid.GetRow
Grid.SetColumn and Grid.GetColumn
Grid.SetRowSpan and Grid.GetRowSpan
Grid.SetColumnSpan and Grid.GetColumnSpan

In XAML you use the following attributes for setting these values:
Grid.Row
Grid.Column
Grid.RowSpan
Grid.ColumnSpan

The SimpleGridDemo sample demonstrates creating and initializing a Grid in XAML.


The Grid inherits the Padding property from Layout and defines two additional properties that provide spacing
between the rows and columns:
RowSpacing has a default value of 6
ColumnSpacing has a default value of 6

The RowDefinitions and ColumnDefinitions collections aren't strictly required. If absent, the Grid creates rows
and columns for the Grid children and gives them all a default GridLength of "*" (star).
The Grid in code
The GridCodeDemo sample demonstrates how to create and populate a Grid in code. You can set the attached
properties for each child directly, or indirectly by calling additional Add methods such as Add defined by the
Grid.IGridList interface.
The Grid bar chart
The GridBarChart sample shows how to add multiple BoxView elements to a Grid using the bulk AddHorizontal
method. By default, these BoxView elements have equal width. The height of each BoxView can then be controlled
to resemble a bar chart.
The Grid in the GridBarChart sample shares an AbsoluteLayout parent with an initially invisible Frame . The
program also sets a TapGestureRecognizer on each BoxView to use the Frame to display information about the
tapped bar.
Alignment in the Grid
The GridAlignment sample demonstrates how to use the VerticalOptions and HorizontalOptions properties to
align children in a Grid cell.
The SpacingButtons sample equally spaces Button elements centered in Grid cells.
Cell dividers and borders
The Grid does not include a feature that draws cell dividers or borders. However, you can make your own.
The GridCellDividers demonstrates how to define additional rows and column specifically for thin BoxView
elements to mimic dividing lines.
The GridCellBorders program does not create any additional cells but instead aligns BoxView elements in each
cell to mimic a cell border.

Almost real-life Grid examples


The KeypadGrid sample uses a Grid to display a keypad:
Responding to orientation changes
The Grid can help structure a program to respond to orientation changes. The GridRgbSliders sample
demonstrates a technique that moves an element between a second row of a portrait-oriented phone and the
second column of a landscape-oriented phone.
The program initializes Slider elements to a range of 0 to 255, and uses data bindings to display the value of the
sliders in hexadecimal. Because the Slider values are floating point, and the .NET formatting string for
hexadecimal only works with integers, a DoubleToIntConvert class in the Xamarin.FormsBook.Toolkit library
helps out.

Related links
Chapter 17 full text (PDF )
Chapter 17 samples
Grid
Summary of Chapter 18. MVVM
4/2/2019 • 4 minutes to read • Edit Online

Download the sample


One of the best ways to architect an application is by separating the user interface from the underlying code, which
is sometimes called the business logic. Several techniques exist, but the one that is tailored for XAML -based
environments is known as Model-View -ViewModel or MVVM.

MVVM interrelationships
An MVVM application has three layers:
The Model provides underlying data, sometimes through files or web accesses
The View is the user interface or presentation layer, generally implemented in XAML
The ViewModel connects the Model and the View
The Model is ignorant of the ViewModel and the ViewModel is ignorant of the View. These three layers generally
connect to each other using the following mechanisms:

In many smaller programs (and even larger ones), often the Model is absent or its functionality is integrated into
the ViewModel.

ViewModels and data binding


To engage in data bindings, a ViewModel must be capable of notifying the View when a property of the
ViewModel has changed. The ViewModel does this by implementing the INotifyPropertyChanged interface in the
System.ComponentModel namespace. This is part of .NET rather than Xamarin.Forms. ( Generally ViewModels
attempt to maintain platform independence.)
The INotifyPropertyChanged interface declares a single event named PropertyChanged that indicates the property
that has changed.
A ViewModel clock
The DateTimeViewModel in the Xamarin.FormsBook.Toolkit library defines a property of type DateTime that
changes based on a timer. The class implements INotifyPropertyChanged and fires the PropertyChanged event
whenever the DateTime property changes.
The MvvmClock sample instantiates this ViewModel and uses data bindings to the ViewModel to display
updated date and time information.
Interactive properties in a ViewModel
Properties in a ViewModel can be more interactive, as demonstrated by the SimpleMultiplierViewModel class,
which is part of the SimpleMultiplier sample. The data bindings provide multiplicand and multiplier values from
two Slider elements and display the product with a Label . However, you can make extensive changes to this
user interface in XAML with no consequent changes to the ViewModel or the code-behind file.
A Color ViewModel
The ColorViewModel in the Xamarin.FormsBook.Toolkit library integrates the RGB and HSL color models. It is
demonstrated in the HslSliders sample:

Streamlining the ViewModel


The code in ViewModels can be streamlined by defining an OnPropertyChanged method using the
CallerMemberName attribute, which obtains the calling property name automatically. The ViewModelBase class in the
Xamarin.FormsBook.Toolkit library does this and provides a base class for ViewModels.

The Command interface


MVVM works with data bindings, and data bindings work with properties, so MVVM seems to be deficient when
it comes to handling a Clicked event of a Button or a Tapped event of a TapGestureRecognizer . To allow
ViewModels to handle such events, Xamarin.Forms supports the command interface.
The command interface manifests itself in the Button with two public properties:
Command of type ICommand (defined in the System.Windows.Input namespace)
CommandParameter of type Object

To support the command interface, a ViewModel must define a property of type ICommand that is then data bound
to the Command property of the Button . The ICommand interface declares two methods and one event:
An Execute method with an argument of type object
A CanExecute method with an argument of type object that returns bool
A CanExecuteChanged event
Internally, a ViewModel sets each property of type ICommand to an instance of a class that implements the
ICommand interface. Through the data binding, the Button initially calls the CanExecute method, and disables itself
if the method returns false . It also sets a handler for the CanExecuteChanged event and calls CanExecute
whenever that event is fired. If the Button is enabled, it calls the Execute method whenever the Button is clicked.
You might have some ViewModels that predate Xamarin.Forms, and these might already support the command
interface. For new ViewModels intended to be used only with Xamarin.Forms, Xamarin.Forms supplies a Command
class and a Command<T> class that implement the ICommand interface. The generic type is the type of the argument
to the Execute and CanExecute methods.
Simple method executions
The PowersOfThree sample demonstrates how to use the command interface in a ViewModel. The
PowersViewModel class defines two properties of type ICommand and also defines two private properties that it
passes to the simplest Command constructor. The program contains data bindings from this ViewModel to the
Command properties of two Button elements.

The Button elements can be easily replaced with TapGestureRecognizer objects in XAML with no code changes.
A calculator, almost
The AddingMachine sample makes use of both the Execute and CanExecute methods of ICommand . It uses an
AdderViewModel class in the Xamarin.FormsBook.Toolkit library. The ViewModel contains six properties of type
ICommand . These are initialized from the Command constructor and Command constructor of Command and the
Command<T> constructor of Command<T> . The numeric keys of the adding machine are all bound to the property that
is initialized with Command<T> , and a string argument to Execute and CanExecute identifies the particular key.

ViewModels and the application lifecycle


The AdderViewModel used in the AddingMachine sample also defines two methods named SaveState and
RestoreState . These methods are called from the application when it goes to sleep and when it starts up again.

Related links
Chapter 18 full text (PDF )
Chapter 18 samples
Enterprise Application Patterns using Xamarin.Forms eBook
Summary of Chapter 19. Collection views
12/7/2018 • 11 minutes to read • Edit Online

Download the sample

NOTE
Notes on this page indicate areas where Xamarin.Forms has diverged from the material presented in the book.

Xamarin.Forms defines three views that maintain collections and display their elements:
is a relatively short list of string items that allows the user to choose one
Picker
ListView is often a long list of items usually of the same type and formatting, also allowing the user to choose
one
TableView is a collection of cells (usually of various types and appearances) to display data or manage user
input
It is common for MVVM applications to use the ListView to display a selectable collection of objects.

Program options with Picker


The Picker is a good choice when you need to allow the user to choose an option from among a relatively short
list of string items.
The Picker and event handling
The PickerDemo sample demonstrates how to use XAML to set the Picker Title property and add string
items to the Items collection. When the user selects the Picker , it displays the items in the Items collection in a
platform-dependent manner.
The SelectedIndexChanged event indicates when the user has selected an item. The zero-based SelectedIndex
property then indicates the selected item. If no item is selected, SelectedIndex equals –1.
You can also use SelectedIndex to initialize the selected item, but it must be set after the Items collection is filled.
In XAML, this means that you'll probably use a property element to set SelectedIndex .
Data binding the Picker
The SelectedIndex property is backed by a bindable property but Items is not, so using data binding with a
Picker is difficult. One solution is to use the Picker in combination with an ObjectToIndexConverter such as the
one in the Xamarin.FormsBook.Toolkit library. The PickerBinding demonstrates how this works.

NOTE
The Xamarin.Forms Picker now includes ItemsSource and SelectedItem properties that support data binding. See
Picker.

Rendering data with ListView


The ListView is the only class that derives from ItemsView<TVisual> from which it inherits the ItemsSource and
ItemTemplate properties.
ItemsSourceis of type IEnumerable but it is null by default and must be explicitly initialized or (more
commonly) set to a collection through a data binding. The items in this collection can be of any type.
ListView defines a SelectedItem property that is either set to one of the items in the ItemsSource collection or
null if no item is selected. ListView fires the ItemSelected event when a new item is selected.
Collections and selections
The ListViewList sample fills a ListView with 17 Color values in a List<Color> collection. The items are
selectable but by default they are displayed with their unattractive ToString representations. Several examples in
this chapter show how to fix that display and make it as attractive as desired.
The row separator
On iOS and Android displays, a thin line separates the rows. You can control this with the SeparatorVisibility
and SeparatorColor properties. SeparatorVisibility property is of type SeparatorVisibility , an enumeration
with two members:
Default , the default setting
None

Data binding the selected item


The SelectedItem property is backed by a bindable property, so it can be either the source or target of a data
binding. Its default BindingMode is OneWayToSource , but generally it is the target of a two-way data binding,
particularly in MVVM scenarios. The ListViewArray sample demonstrates this type of binding.
The ObservableCollection difference
The ListViewLogger sample sets the ItemsSource property of a ListView to a List<DateTime> collection and
then progressively adds a new DateTime object to the collection every second using a timer.
However, the ListView doesn't automatically update itself because the List<T> collection doesn't have a
notification mechanism to indicate when items are added to or removed from the collection.
A much better class to use in such scenarios is ObservableCollection<T> defined in the
System.Collections.ObjectModel namespace. This class implements the INotifyCollectionChanged interface and
consequently fires a CollectionChanged event when items are added to or removed from the collection, or when
they are replaced or moved within the collection. When the ListView internally detects that a class implementing
INotifyCollectionChanged has been set to its ItemsSource property, it attaches a handler to the CollectionChanged
event and updates its display when the collection changes.
The ObservableLogger sample demonstrates the use of ObservableCollection .
Templates and cells
By default, a ListView displays items in its collection using each item's ToString method. A better approach
involves defining a template to display the items.
To experiment with this feature, you can use the NamedColor class in the Xamarin.FormsBook.Toolkit library.
This class defines a static All property of type IList<NamedColor> that contains 141 NamedColor objects
corresponding to the public fields of the Color structure.
The NaiveNamedColorList sample sets the ItemsSource of a ListView to this NamedColor.All property, but
only the fully-qualified class names of the NamedColor objects are displayed.
ListView needs a template to display these items. In code, you can set the ItemTemplate property defined by
ItemsView<TVisual> to a DataTemplate object using the DataTemplate constructor that references a derivative of
the Cell class. Cell has five derivatives:
TextCell — contains two Label views (conceptually speaking)
ImageCell — adds an Image view to TextCell
EntryCell — contains an Entry view with a Label
SwitchCell — contains a Switch with a Label
ViewCell — can be any View (likely with children)

Then call SetValue and SetBinding on the DataTemplate object to associate values with the Cell properties, or
to set data bindings on the Cell properties referencing properties of the items in the ItemsSource collection. This
is demonstrated in the TextCellListCode sample.
As each item is displayed by the ListView , a small visual tree is constructed from the template, and data bindings
are established between the item and the properties of the elements in this visual tree. You can get an idea of this
process by installing handlers for the ItemAppearing and ItemDisappearing events of the ListView , or by using an
alternative DataTemplate constructor that uses a function that is called each time an item's visual tree must be
created.
The TextCellListXaml shows a functionally identical program entirely in XAML. A DataTemplate tag is set to the
ItemTemplate property of the ListView , and then the TextCell is set to the DataTemplate . Bindings to properties
of the items in the collection are set directly on the Text and Detail properties of the TextCell .
Custom cells
In XAML it is possible to set a ViewCell to the DataTemplate and then define a custom visual tree as the View
property of ViewCell . ( View is the content property of ViewCell so the ViewCell.View tags aren't required.) The
CustomNamedColorList sample demonstrates this technique:

Getting the sizing right for all the platforms can be tricky. The RowHeight property is useful but in some cases
you'll want to resort to the HasUnevenRows property, which is less efficient but forces the ListView to size the
rows. For iOS and Android, you must use one of these two properties to get proper row sizing.
Grouping the ListView items
ListView supports the grouping of items and navigating among those groups. The ItemsSource property must
be set to a collection of collections: The object that ItemsSource is set to must implement IEnumerable , and each
item in the collection must also implement IEnumerable . Each group should include two properties: a text
description of the group and a three-letter abbreviation.
The NamedColorGroup class in the Xamarin.FormsBook.Toolkit library creates seven groups of NamedColor
objects. The ColorGroupList sample shows how to use these groups with the IsGroupingEnabled property of
ListView set to true , and the GroupDisplayBinding and GroupShortNameBinding properties bound to properties in
each group.
Custom group headers
It's possible to create custom headers for the ListView groups by replacing the GroupDisplayBinding property
with the GroupHeaderTemplate defining a template for the headers.
ListView and interactivity
Generally an application obtains user interaction with a ListView by attaching a handler to the ItemSelected or
ItemTapped event, or by setting a data binding on the SelectedItem property. But some cell types ( EntryCell and
SwitchCell ) allow user interaction, and it's also possible to create custom cells that themselves interact with the
user. The InteractiveListView creates 100 instances of ColorViewModel and allows the user to change each color
using a trio of Slider elements. The program also makes use of the ColorToContrastColorConverter in the
Xamarin.FormsBook.Toolkit.

ListView and MVVM


ListView plays a big role in MVVM scenarios. Whenever an IEnumerable collection exists in a ViewModel, it is
often bound to a ListView . Also, the items in the collection often implement INotifyPropertyChanged to bind with
properties in a template.
A collection of ViewModels
To explore this, the SchoolOfFineArts library creates several classes based on an XML data file and images of
fictitious students at this fictitious school.
The Student class derives from ViewModelBase . The StudentBody class is a collection of Student objects and also
derives from ViewModelBase . The SchoolViewModel downloads the XML file and assembles all the objects.
The StudentList program uses an ImageCell to display the students and their images in a ListView :

The ListViewHeader sample adds a Header property but it only shows up on Android.
Selection and the binding context
The SelectedStudentDetail program binds the BindingContext of a StackLayout to the SelectedItem property
of the ListView . This allows the program to display detailed information about the selected student.
Context menus
A cell can define a context menu that is implemented in a platform-specific manner. To create this menu, add
MenuItem objects to the ContextActions property of the Cell .
MenuItem defines five properties:
Text of type string
Icon of type FileImageSource
IsDestructive of type bool
Command of type ICommand
CommandParameter of type object

The Command and CommandParameter properties imply that the ViewModel for each item contains methods to carry
out the desired menu commands. In non-MVVM scenarios, MenuItem also defines a Clicked event.
The CellContextMenu demonstrates this technique. The Command property of each MenuItem is bound to a
property of type ICommand in the Student class. Set the IsDestructive property to true for a MenuItem that
removes or deletes the selected object.
Varying the visuals
Sometimes you'll want slight variations in the visuals of the items in the ListView based on a property. For
example, when a student's grade-point average falls below 2.0, the ColorCodedStudents sample displays that
student's name in red. This is accomplished through use of a binding value converter, ThresholdToObjectConverter ,
in the Xamarin.FormsBook.Toolkit library.
Refreshing the content
The ListView supports a pull-down gesture for refreshing its data. The program must set the IsPullToRefresh
property to true to enable this. The ListView responds to the pull-down gesture by setting its IsRefreshing
property to true , and by raising the Refreshing event and (for MVVM scenarios) calling the Execute method of
its RefreshCommand property.
Code handling the Refresh event or the RefreshCommand then possibly updates the data displayed by the
ListView and sets IsRefreshing back to false .
The RssFeed sample demonstrates using an RssFeedViewModel that implements RefreshCommand and
IsRefreshing properties for data binding.

The TableView and its intents


While the ListView generally displays multiple instances of the same type, the TableView is generally focused on
providing a user interface for multiple properties of various types. Each item is associated with its own Cell
derivative for displaying the property or providing a user interface to it.
Properties and hierarchies
TableView defines only four properties:

Intent of type TableIntent , an enumeration


Root of type TableRoot , the content property of TableView
RowHeight of type int
HasUnevenRows of type bool

The TableIntent enumeration indicates how you intend to use the TableView :
Data
Form
Settings
Menu
These members also suggest some uses for the TableView .
Several other classes are involved in defining a table:
TableSectionBase is an abstract class that derives from BindableObject and defines a Title property
TableSectionBase<T> is an abstract class that derives from TableSectionBase and implements IList<T>
and INotifyCollectionChanged

TableSection derives from TableSectionBase<Cell>

TableRoot derives from TableSectionBase<TableSection>

In short, TableView has a Root property that you set to a TableRoot object, which is a collection of TableSection
objects, each of which is a collection of Cell objects. A table has multiple sections, and each section has multiple
cells. The table itself can have a title, and each section can have a title. Although TableView makes use of Cell
derivatives, it does not make use of DataTemplate .
A prosaic form
The EntryForm sample defines a PersonalInformation view model, an instance of which becomes the
BindingContext of the TableView . Each Cell derivative in its TableSection can then have bindings to properties
of the PersonalInformation class.
Custom cells
The ConditionalCells sample expands on EntryForm. The ProgrammerInformation class includes a Boolean
property that governs the applicability of two additional properties. For these two additional properties, the
program uses a custom PickerCell based on a PickerCell.xaml and PickerCell.xaml.cs in the
Xamarin.FormsBook.Toolkit library.
Although the IsEnabledproperties of the two PickerCell elements are bound to the Boolean property in
ProgrammerInformation , this technique does not seem to work, which prompts the next sample.

Conditional sections
The ConditionalSection sample puts the two items that are conditional on the selection of the Boolean item in a
separate TableSection . The code-behind file removes this section from the TableView or adds it back based on
the Boolean property.
A TableView menu
Another use of a TableView is a menu. The MenuCommands sample demonstrates a menu that lets you move a
little BoxView around the screen.

Related links
Chapter 19 full text (PDF )
Chapter 19 samples
Picker
ListView
TableView
Summary of Chapter 20. Async and file I/O
7/8/2019 • 7 minutes to read • Edit Online

Download the sample

NOTE
Notes on this page indicate areas where Xamarin.Forms has diverged from the material presented in the book.

A graphical user interface must respond to user-input events sequentially. This implies that all processing of user-
input events must occur in a single thread, often called the main thread or the UI thread.
Users expect graphical user interfaces to be responsive. This means that a program must process user-input events
quickly. If that is not possible, then processing must be relegated to secondary threads of execution.
Several sample programs in this book have used the WebRequest class. In this class the BeginGetResponse method
starts a worker thread, which calls a callback function when it is complete. However, that callback function runs in
the worker thread, so the program must call Device.BeginInvokeOnMainThread method to access the user interface.

NOTE
Xamarin.Forms programs should use HttpClient rather than WebRequest for accessing files over the internet.
HttpClient supports asynchronous operations.

A more modern approach to asynchronous processing is available in .NET and C#. This involves the Task and
Task<TResult> classes, and other types in the System.Threading and System.Threading.Tasks namespaces, as well
as the C# 5.0 async and await keywords. That's what this chapter focuses on.

From callbacks to await


The Page class itself contains three asynchronous methods to display alert boxes:
DisplayAlert returns a Task object
DisplayAlert returns a Task<bool> object
DisplayActionSheet returns a Task<string> object

The Task objects indicate that these methods implement the Task-based Asynchronous Pattern, known as TAP.
These Task objects are returned quickly from the method. The Task<T> return values constitute a "promise" that a
value of type TResult will be available when the task completes. The Task return value indicates an asynchronous
action that will complete but with no value returned.
In all these cases, the Task is complete when the user dismisses the alert box.
An alert with callbacks
The AlertCallbacks sample demonstrates how to handle Task<bool> return objects and
Device.BeginInvokeOnMainThread calls using callback methods.

An alert with lambdas


The AlertLambdas sample demonstrates how to use anonymous lambda functions for handling Task and
Device.BeginInvokeOnMainThread calls.
An alert with await
A more straightforward approach involves the async and await keywords introduced in C# 5. The AlertAwait
sample demonstrates their use.
An alert with nothing
If the asynchronous method returns Task rather than Task<TResult> , then the program doesn't need to use any of
these techniques if it doesn't need to know when the asynchronous task completes. The NothingAlert sample
demonstrates this.
Saving program settings asynchronously
The SaveProgramChanges sample demonstrates the use of the SavePropertiesAsync method of Application to
save program settings as they change without overriding the OnSleep method.
A platform-independent timer
It's possible to use Task.Delay to create a platform-independent timer. The TaskDelayClock sample demonstrates
this.

File input/output
Traditionally, the .NET System.IO namespace has been the source of file I/O support. Although some methods in
this namespace support asynchronous operations, most do not. The namespace also supports several simple
method calls that perform sophisticated file I/O functions.
Good news and bad news
All the platforms supported by Xamarin.Forms support application local storage — storage that is private to the
application.
The Xamarin.iOS and Xamarin.Android libraries include a version of .NET that Xamarin has expressly tailored for
these two platforms. These include classes from System.IO that you can use to perform file I/O with application
local storage in these two platforms.
However, if you search for these System.IO classes in a Xamarin.Forms PCL, you won't find them. The problem is
that Microsoft completely revamped file I/O for the Windows Runtime API. Programs targeting Windows 8.1,
Windows Phone 8.1, and the Universal Windows Platform do not use System.IO for file I/O.
This means that you'll need to use the DependencyService (first discussed in Chapter 9. Platform -specific API
calls to implement file I/O.

NOTE
Portable Class Libaries have been replaced with .NET Standard 2.0 libraries, and .NET Standard 2.0 supports System.IO
types for all Xamarin.Forms platforms. It is no longer necessary to use a DependencyService for most file I/O tasks. See File
Handling in Xamarin.Forms for a more modern approach to file I/O.

A first shot at cross-platform file I/O


The TextFileTryout sample defines an IFileHelper interface for file I/O, and implementations of this interface in
all the platforms. However, the Windows Runtime implementations don't work with the methods in this interface
because the Windows Runtime file I/O methods are asynchronous.
Accommodating Windows Runtime file I/O
Programs running under the Windows Runtime use classes in the Windows.Storage and Windows.Storage.Streams
namespaces for file I/O, including application local storage. Because Microsoft determined that any operation
requiring more than 50 milliseconds should be asynchronous to avoid blocking the UI thread, these file I/O
methods are mostly asynchronous.
The code demonstrating this new approach will be in a library so that it can be used by other applications.

Platform-specific libraries
It's advantageous to store reusable code in libraries. This is obviously more difficult when different pieces of the
reusable code are for entirely different operating systems.
The Xamarin.FormsBook.Platform solution demonstrates one approach. This solution contains seven different
projects:
Xamarin.FormsBook.Platform, a normal Xamarin.Forms PCL
Xamarin.FormsBook.Platform.iOS, an iOS class library
Xamarin.FormsBook.Platform.Android, an Android class library
Xamarin.FormsBook.Platform.UWP, a Universal Windows class library
Xamarin.FormsBook.Platform.WinRT, a shared project for code that is common to all the Windows
platforms
All the individual platform projects (with the exception of Xamarin.FormsBook.Platform.WinRT) have
references to Xamarin.FormsBook.Platform. The three Windows projects have a reference to
Xamarin.FormsBook.Platform.WinRT.
All the projects contain a static Toolkit.Init method to ensure that the library is loaded if it's not directly
referenced by a project in a Xamarin.Forms application solution.
The Xamarin.FormsBook.Platform project contains the new IFileHelper interface. All the methods now have
names with Async suffixes and return Task objects.
The Xamarin.FormsBook.Platform.WinRT project contains the FileHelper class for the Windows Runtime.
The Xamarin.FormsBook.Platform.iOS project contains the FileHelper class for iOS. These methods must now
be asynchronous. Some of the methods use the asynchronous versions of methods defined in StreamWriter and
StreamReader : WriteAsync and ReadToEndAsync . Others convert a result to a Task object using the FromResult
method.
The Xamarin.FormsBook.Platform.Android project contains a similar FileHelper class for Android.
The Xamarin.FormsBook.Platform project also contains a FileHelper class that eases the use of the
DependencyService object.

To use these libraries, an application solution must include all the projects in the Xamarin.FormsBook.Platform
solution, and each of the application projects must have a reference to the corresponding library in
Xamarin.FormsBook.Platform.
The TextFileAsync solution demonstrates how to use the Xamarin.FormsBook.Platform libraries. Each of the
projects has a call to Toolkit.Init . The application makes use of the asynchronous file I/O functions.
Keeping it in the background
Methods in libraries that make calls to multiple asynchronous methods — such as the WriteFileAsync and
ReadFileASync methods in the Windows Runtime FileHelper class — can be made somewhat more efficient by
using the ConfigureAwait method to avoid switching back to the user-interface thread.
Don't block the UI thread!
Sometimes it's tempting to avoid the use of ContinueWith or await by using the Result property on the
methods. This should be avoided for it can block the UI thread or even hang the application.

Your own awaitable methods


You can run some code asynchronously by passing it to one of the Task.Run methods. You can call Task.Run
within an async method that handles some of the overhead.
The various Task.Run patterns are discussed below.
The basic Mandelbrot set
To draw the Mandelbrot set in real time, the Xamarin.Forms.Toolkit library has a Complex structure similar to the
one in the System.Numerics namespace.
The MandelbrotSet sample has a CalculateMandeblotAsync method in its code-behind file that calculates the basic
black-and-white Mandelbrot set and uses BmpMaker to put it on a bitmap.
Marking progress
To report progress from an asynchronous method, you can instantiate a Progress<T> class and define your
asynchronous method to have an argument of type IProgress<T> . This is demonstrated in the
MandelbrotProgress sample.
Cancelling the job
You can also write an asynchronous method to be cancellable. You begin with a class named
CancellationTokenSource . The Token property is a value of type CancellationToken . This is passed to the
asynchronous function. A program calls the Cancel method of CancellationTokenSource (generally in response to
an action by the user) to cancel the asynchronous function.
The asynchronous method can periodically check the IsCancellationRequested property of CancellationToken and
exit if the property is true , or simply call the ThrowIfCancellationRequested method, in which case the method
ends with an OperationCancelledException .
The MandelbrotCancellation sample demonstrates the use of a cancellable function.
An MVVM Mandelbrot
The MandelbrotXF sample has a more extensive user interface, and it's mostly based on a MandelbrotModel and
MandelbrotViewModel classes:

Back to the web


The WebRequest class used in some samples uses an old-fashioned asynchronous protocol called the
Asynchronous Programming Model or APM. You can convert such a class to the modern TAP protocol using one
of the FromAsync methods in the TaskFactory class. The ApmToTap sample demonstrates this.
Related links
Chapter 20 full text (PDF )
Chapter 20 samples
Working with Files
Summary of Chapter 21. Transforms
7/2/2019 • 5 minutes to read • Edit Online

Download the sample


A Xamarin.Forms view appears on the screen in a location and size determined by its parent, which is generally a
Layout or Layout<View> derivative. The transform is a Xamarin.Forms feature that can modify that location, size,
or even orientation.
Xamarin.Forms supports three basic types of transforms:
Translation — shift an element horizontally or vertically
Scale — change the size of an element
Rotation — turn an element around a point or axis
In Xamarin.Forms, the scaling is isotropic; it affects the width and height uniformly. Rotation is supported both on
the two-dimensional surface of the screen and in 3D space. There is no skew (or sheer) transform, and no
generalized matrix transform.
Transforms are supported with eight properties of type double defined by the VisualElement class:
TranslationX
TranslationY
Scale
Rotation
RotationX
RotationY
AnchorX
AnchorY

All these properties are backed by bindable properties. They can be targets of data binding and styled. Chapter 22.
Animation demonstrates how these properties can be animated, but some samples in this chapter show how you
can animate them using the Xamarin.Forms timer.
Transform properties affect only how the element is rendered, and do not affect how the element is perceived in
layout.

The translation transform


Nonzero values of the TranslationX and TranslationY properties shift an element horizontally or vertically.
The TranslationDemo program allows you to experiment with these properties with two Slider elements that
control the TranslationX and TranslationY properties of a Frame . The transform also affects all children of that
Frame .

Text effects
One common use of the translation properties is to offset slightly the rendering of text. This is demonstrated in the
TextOffsets sample:
Another effect is to render multiple copies of a Label to resemble a 3D block, such as demonstrated in the
BlockText sample.
Jumps and animations
The ButtonJump sample uses translation to move a Button whenever it's tapped, but the primary intent is to
demonstrate that the Button receives user input at the location where the button is rendered.
The ButtonGlide sample is similar but uses a timer to animate the Button from one point to another.

The scale transform


The Scale transform can increase or decrease the rendered size of the element. The default value is 1. A value of 0
causes the element to be invisible. Negative values cause the element to appear to be rotated 180 degrees. The
Scale property does not affect the Width or Height properties of the element. Those values remain the same.

You can experiment with the Scale property using the SimpleScaleDemo sample.
The ButtonScaler sample demonstrates the difference between animating the Scale property of a Button and
animating the FontSize property. The FontSize property affects how the Button is perceived in layout; the
Scale property does not.

The ScaleToSize sample calculates a Scale property that is applied to a Label element to make it as large as
possible while still fitting within the page.
Anchoring the scale
The elements scaled in the previous three samples have all increased or decreased in size relative to the center of
the element. In other words, the element increases or decreases in size the same in all directions. Only the point at
the center of the element remains in the same location during the scaling.
You can change the center of the scaling by setting the AnchorX and AnchorY properties. These properties are
relative to the element itself. For AnchorX , a value of 0 refers to the left side of the element and 1 refers to the right
side. Similarly for AnchorY , 0 is the top and 1 is the bottom. Both properties have default values of 0.5, which is the
center.
The AnchoredScaleDemo sample allows you to experiment with the AnchorX and AnchorY properties as well as
the Scale property.
On iOS, using non-default values of AnchorX and AnchorY properties is generally incompatible with phone
orientation changes.
The rotation transform
The Rotation property is specified in degrees and indicates clockwise rotation around a point of the element
defined by AnchorX and AnchorY . The PlaneRotationDemo allows you to experiment with these three
properties.
Rotated text effects
The BoxViewCircle sample demonstrates the mathematics necessary to draw a circle using 64 tiny rotated
BoxView elements.

The RotatedText sample displays multiple Label elements with the same text string rotated to appear like spokes.
The CircularText sample displays a text string that appears to wrap in a circle.
An analog clock
The Xamarin.FormsBook.Toolkit library contains an AnalogClockViewModel class that calculates angles for the
hands of a clock. To avoid platform dependencies in the ViewModel, the class uses Task.Delay rather than a timer
for finding a new DateTime value.
Also included in Xamarin.FormsBook.Toolkit is a SecondTickConverter class that implements IValueConverter
and serves to round a second angle to the nearest second.
The MinimalBoxViewClock uses three rotating BoxView elements to draw an analog clock.
The BoxViewClock uses BoxView for more extensive graphics, including tick marks around the face of the clock,
and hands that rotate a little distance from their ends:

In addition a SecondBackEaseConverter class in Xamarin.FormsBook.Toolkit causes the second hand to appear to


pull back a little before jumping ahead, and then to move back into its correct position.
Vertical sliders?
The VerticalSliders sample demonstrates that Slider elements can be rotated 90 degrees and still function.
However, it's difficult to position these rotated Slider elements because in layout they still appear to be
horizontal.

3D-ish rotations
The RotationX property appears to rotate an element around a 3D X-axis so that the top and bottom of the
element seem to move towards or away from the viewer. Similarly, the RotationY seems to rotate an element
around the Y -axis to make the left and right sides of the element seem to move towards or away from the viewer.
The AnchorX property affects RotationY but not RotationX . The AnchorY property affects RotationX but not
RotationY . You can experiment with the ThreeDeeRotationDemo sample to explore the interactions of these
properties.
The 3D coordinate system implied by Xamarin.Forms is left-handed. If you point the forefinger of your left hand in
the direction of increasing X coordinates (to the right) and your middle finger in the direction of increasing Y
coordinates (down), then your thumb points in the direction of increasing Z coordinates (out of the screen).
Also, for any of the three axis, if you point your left-hand thumb in the direction of increasing values, then the curve
of your fingers indicates the direction of rotation for positive rotating angles.

Related links
Chapter 21 full text (PDF )
Chapter 21 samples
Summary of Chapter 22. Animation
12/7/2018 • 8 minutes to read • Edit Online

Download the sample


You've seen that you can create your own animations using the Xamarin.Forms timer or Task.Delay , but it is
generally easier using the animation facilities provided by Xamarin.Forms. Three classes implement these
animations:
ViewExtensions , the high-level approach
Animation , more versatile but harder
AnimationExtension , the most versatile, lowest-level approach

Generally, animations target properties that are backed by bindable properties. This is not a requirement but these
are the only properties that dynamically react to changes.
There is no XAML interface for these animations, but you can integrate animations into XAML using techniques
discussed in Chapter 23. Triggers and Behaviors.

Exploring basic animations


The basic animation functions are extension methods found in the ViewExtensions class. These methods apply to
any object that derives from VisualElement . The simplest animations target the transforms properties discussed in
Chapter 21. Transforms .

The AnimationTryout demonstrates how the Clicked event handler for a Button can call the RotateTo
extension method to spin the button in a circle.
The RotateTo method changes the Rotation property of the Button from 0 to 360 over the course of one-
quarter second (by default). If the Button is tapped again, however, it does nothing because the Rotation
property is already 360 degrees.
Setting the animation duration
The second argument to RotateTo is a duration in milliseconds. If set to a large value, tapping the Button during
an animation starts a new animation beginning at the current angle.
Relative animations
The RelRotateTo method performs a relative rotation by adding a specified value to the existing value. This
method allows the Button to be tapped multiple times, and each time increases the Rotation property by 360
degrees.
Awaiting animations
All the animation methods in ViewExtensions return Task<bool> objects. This means that you can define a series
of sequential animations using ContinueWith or await . The bool completion return value is false if the
animation finished without interruption or true if it was cancelled by the CancelAnimation method, which cancels
all animations initiated by the other method in ViewExtensions that are set on the same element.
Composite animations
You can mix awaited and non-awaited animations to create composite animations. These are the animations in
ViewExtensions that target the TranslationX , TranslationY , and Scale transform properties:
TranslateTo
ScaleTo
RelScaleTo

Notice that TranslateTo potentially affects both the TranslationX and TranslationY properties.
Task.WhenAll and Task.WhenAny
It is also possible to manage simultaneous animations using Task.WhenAll , which signals when multiple tasks
have all concluded, and Task.WhenAny , which signals when the first of several tasks has concluded.
Rotation and anchors
When calling the ScaleTo , RelScaleTo , RotateTo , and RelRotateTo methods, you can set the AnchorX and
AnchorY properties to indicate the center of scaling and rotation.

The CircleButton demonstrates this technique by revolving a Button around the center of the page.
Easing functions
Generally animations are linear from a start value to an end value. Easing functions can cause animations to speed
up or slow down over their course. The last optional argument to the animation methods is of type Easing , a class
that defines 11 static read-only fields of type Easing :
Linear , the default
SinIn , SinOut , and SinInOut
CubicIn , CubicOut , and CubicInOut
BounceIn and BounceOut
SpringIn and SpringOut

The In suffix indicates that the effect is at the beginning of the animation, Out means at the end, and InOut
means that it's at the beginning and end of the animation.
The BounceButton sample demonstrates the use of easing functions.
Your own easing functions
You can also define you own easing functions by passing a Func<double, double> to the Easing constructor.
Easing also defines an implicit conversion from Func<double, double> to Easing . The argument to the easing
function is always in the range of 0 to 1 as the animation proceeds linearly from beginning to end. The function
usually returns a value in the range of 0 to 1, but could be briefly negative or greater than 1 (as is the case with the
SpringIn and SpringOut functions) or could break the rules if you know what you're doing.

The UneasyScale sample demonstrates a custom easing function, and CustomCubicEase demonstrates another.
The SwingButton sample also demonstrates a custom easing function, and also a technique of changing the
AnchorX and AnchorY properties within a sequence of rotation animations.

The Xamarin.FormsBook.Toolkit library has a JiggleButton class that uses a custom easing function to jiggle a
button when it's clicked. The JiggleButtonDemo sample demonstrates it.
Entrance animations
One popular type of animation occurs when a page first appears. Such an animation can be started in the
OnAppearing override of the page. For these animations, its best to set up the XAML for how you want the page to
appear after the animation, and then initialize and animate the layout from code.
The FadingEntrance sample uses the FadeTo extension method to fade in the contents of the page.
The SlidingEntrance sample uses the TranslateTo extension method to slide in the contents of the page from
the sides.
The SwingingEntrance sample uses the RotateYTo extension method to animate the RotationY property. A
RotateXTo method is also available.

Forever animations
At the other extreme, "forever" animations run until the program is terminated. These are generally intended for
demonstration purposes.
The FadingTextAnimation sample uses FadeTo animation to fade two pieces of text in and out.
PalindromeAnimation displays a palindrome, and then sequentially rotates the individual letters by 180 degrees
so they're all upside-down. Then the entire string is flipped 180 degrees to read the same as the original string.
The CopterAnimation sample rotates a simple BoxView helicopter while revolving it around the center of the
screen.
RotatingSpokes revolves BoxView spokes around the center of the screen, and then rotates each spoke itself to
create interesting patterns:

However, progressively increasing the Rotation property of an element might not work in the long term, as the
RotationBreakdown sample demonstrates.
The SpinningImage sample uses RotateTo , RotateXTo , and RotateYTo to make it seem as if a bitmap is rotating
in 3D space.
Animating the bounds property
The only extension method in ViewExtensions not yet demonstrated is LayoutTo , which effectively animates the
read-only Bounds property by calling the Layout method. This method is normally called by Layout derivatives
as will be discussed in Chapter 26. CustomLayouts.
The LayoutTo method should be restricted to special purposes. The BouncingBox program uses it to compress
and expand a BoxView as it bounces off the sides of a page.
The XamagonXuzzle sample uses LayoutTo to move tiles in an implementation of the classic 15-16 puzzle that
displays a scrambled image rather than numbered tiles:
Your own awaitable animations
The TryAwaitableAnimation sample creates an awaitable animation. The crucial class that can return a Task
object from the method and signal when the animation is completed is TaskCompletionSource .

Deeper into animations


The Xamarin.Forms animation system can be a little confusing. In addition to the Easing class, the animation
system comprises the ViewExtensions , Animation , and AnimationExtension classes.
ViewExtensions class
You've already seen ViewExtensions . It defines nine methods that return Task<bool> and CancelAnimations . Seven
of the nine methods target transform properties. The other two are FadeTo , which targets the Opacity property,
and LayoutTo , which calls the Layout method.
Animation class
The Animation class has a constructor with five arguments to define callback and finished methods, and
parameters of the animation.
Child animations can be added with Add , Insert , WithConcurrent , and overload of WithConcurrent .
The animation object is then started with a call to the Commit method.
AnimationExtensions class
The AnimationExtensions class contains mostly extension methods. There are several versions of an Animate
method and the generic Animate method is so versatile that it's really the only animation function you need.

Working with the Animation class


The ConcurrentAnimations sample demonstrates the Animation class with several different animations.
Child animations
The ConcurrentAnimations sample also demonstrates child animations, which make use of the (very similar)
Add and Insert methods.

Beyond the high-level animation methods


The ConcurrentAnimations sample also demonstrates how to perform animations that go beyond the
properties targeted by the ViewExtensions methods. In one example, a series of periods get longer; in another
example, a BackgroundColor property is animated.
More of your own awaitable methods
The TranslateTo method of ViewExtensions doesn't work with the Easing.SpringOut function. It stops when the
easing output gets above 1.
The Xamarin.FormsBook.Toolkit library contains a MoreViewExtensions class with TranslateXTo and
TranslateYTo extension methods that don't have this problem, as well as CancelTranslateXTo and
CancelTranslateYTo methods for cancelling those animations.

The SpringSlidingEntrance demonstrates the TranslateXTo method.


The MoreExtensions class also contains a TranslateXYTo extension method that combines X and Y translation, and
a CancelTranslateXYTo method.
Implementing a Bezier animation
It is also possible to develop an animation that moves an element along the path of a Bezier spline. The
Xamarin.FormsBook.Toolkit library contains a BezierSpline structure that encapsulates a Bezier spline and a
BezierTangent enumeration to control orientation.

The MoreViewExtensions class contains a BezierPathTo extension method and a CancelBezierPathTo method.
The BezierLoop sample demonstrates animating an element along a Beizer path.

Working with AnimationExtensions


One type of animation missing from the standard collection is a color animation. The problem is that there is no
right way to interpolate between two Color values. It's possible to interpolate the individual RGB values, but just
as valid is interpolating the HSL values.
For this reason, the MoreViewExtensions class in the Xamarin.FormsBook.Toolkit library contains two Color
animation methods: RgbColorAnimation and HslColorAnimation . (There are also two cancellation methods:
CancelRgbColorAnimation and CancelHslColorAnimation ).

Both methods make use of ColorAnimation , which performs the animation by calling the extensive generic
Animate method in AnimationExtensions .

The ColorAnimations sample demonstrates using these two types of color animations.

Structuring your animations


It's sometimes useful to express animations in XAML and use them in conjunction with MVVM. This is covered in
the next chapter, Chapter 23. Triggers and Behaviors.

Related links
Chapter 22 full text (PDF )
Chapter 22 samples
Animation
Summary of Chapter 23. Triggers and behaviors
12/7/2018 • 7 minutes to read • Edit Online

Download the sample


Triggers and behaviors are similar, in that they are both intended to be used in XAML files to simplify element
interactions beyond the use of data bindings, and to extend the functionality of XAML elements. Both triggers and
behaviors are almost always used with visual user-interface objects.
To support triggers and behaviors, both VisualElement and Style support two collection properties:
VisualElement.Triggers and Style.Triggers of type IList<TriggerBase>
VisualElement.Behaviors and Style.Behaviors of type IList<Behavior>

Triggers
A trigger is a condition (a property change or the firing of an event) that results in a response (another property
change or running some code). The Triggers property of VisualElement and Style is of type
IList<TriggersBase> . TriggerBase is an abstract class from which four sealed classes derive:

Trigger for responses based on property changes


EventTrigger for responses based on event firings
DataTrigger for responses based on data bindings
MultiTrigger for responses based on multiple triggers

The trigger is always set on the element whose property is being changed by the trigger.
The simplest trigger
The Trigger class checks for a change of a property value and responds by setting another property of the same
element.
Trigger defines three properties:
Property of type BindableProperty
Value of type Object
Setters of type IList<SetterBase> , the content property of Trigger

In addition, Trigger requires that the following property inherited from TriggerBase be set:
TargetType to indicate the type of the element on which the Trigger is attached
The Property and Value comprise the condition, and the Setters collection is the response. When the indicated
Property has the value indicated by Value , then the Setter objects in the Setters collection are applied. When
the Property has a different value, the setters are removed. Setter defines two properties that are the same as
the first two properties of Trigger :
Property of type BindableProperty
Value of type Object
The EntryPop sample demonstrates how a Trigger applied to an Entry can increase the size of the Entry via
the Scale property when the IsFocused property of the Entry is true .
Although it's not common, the Trigger can be set in code, as the EntryPopCode sample demonstrates.
The StyledTriggers sample demonstrates how the Trigger can be set in a Style to apply to multiple Entry
elements.
Trigger actions and animations
It is also possible to run a little code based on a trigger. This code can be an animation that targets a property. One
common way is to use an EventTrigger , which defines two properties:
Event of type string , the name of an event
Actions of type IList<TriggerAction> , a list of actions to run in response.

To use this, you need to write a class that derives from TriggerAction<T> , generally TriggerAction<VisualElement> .
You can define properties in this class. These are plain CLR properties rather than bindable properties because
TriggerAction doesn't derive from BindableObject . You must override the Invoke method that is called when the
action is invoked. The argument is the target element.
The ScaleAction class in the Xamarin.FormsBook.Toolkit library is an example. It calls the ScaleTo property to
animate the Scale property of an element. Because one of its properties is of type Easing , the EasingConverter
class lets you use the standard Easing static fields in XAML.
The EntrySwell sample demonstrates how to invoke the ScaleAction from EventTrigger objects that monitor
the Focused and Unfocused events.
The CustomEasingSwell sample shows how to define a custom easing function for ScaleAction in a code-
behind file.
You can also invoke actions using a Trigger (as distinguished from EventTrigger ). This requires that you are
aware that TriggerBase defines two collections:
EnterActions of type IList<TriggerAction>
ExitActions of type IList<TriggerAction>
The EnterExitSwell sample demonstrates how to use these collections.
More event triggers
The ScaleUpAndDownAction class in the Xamarin.FormsBook.Toolkit library calls ScaleTo twice to scale up and
down. The ButtonGrowth sample uses this in a styled EventTrigger to provide visual feedback when a Button is
pressed. This double animation is also possible using two actions in the collection of type DelayedScaleAction
The ShiverAction class in the Xamarin.FormsBook.Toolkit library defines a customizable shiver action. The
ShiverButtonDemo sample demonstrates it.
The NumericValidationAction class in the Xamarin.FormsBook.Toolkit library is restricted to Entry elements
and sets the TextColor property to red if the Text property is not a double . The TriggerEntryValidation
sample demonstrates it.
Data triggers
The DataTrigger is similar to the Trigger except that instead of monitoring a property for value changes, it
monitors a data binding. This allows a property in one element to affect a property in another element.
DataTrigger defines three properties:
Binding of type BindingBase
Value of type Object
Setters of type IList<SetterBase>
The GenderColors sample requires the SchoolOfFineArt library and sets the colors of the names of the students
to blue or pink based on the Sex property:

The ButtonEnabler sample sets the IsEnabled property of an Entry to False if the Length property of the
Text property of the Entry equals 0. Notice that the Text property is initialized to an empty string; by default it
is null , and the DataTrigger wouldn't work correctly.
Combining conditions in the MultiTrigger
The MultiTrigger is a collection of conditions. When they are all true , then setters are applied. The class defines
two properties:
Conditions of type IList<Condition>
Setters of type IList<Setter>
Condition is an abstract class and has two descendent classes:
PropertyCondition , which has Property and Value properties like Trigger
BindingCondition , which has Binding and Value properties like DataTrigger

In the AndConditions sample, a BoxView is only colored when four Switch elements are all turned on.
The OrConditions sample demonstrates how you can make a BoxView a color when any of four Switch
elements are turned on. This requires an application of De Morgan's Law and reversing all the logic.
Combining AND and OR logic is not so easy and generally requires invisible Switch elements for intermediate
results. The XorConditions sample demonstrates how a Button can be enabled if either of two Entry elements
have some text typed in, but not if they both have some text typed in.

Behaviors
Anything you can do with a trigger, you can also do with a behavior, but behaviors always require a class that
derives from Behavior<T> and overrides the following two methods:
OnAttachedTo
OnDetachingFrom

The argument is the element that the behavior is attached to. Generally, the OnAttachedTo method attaches some
event handlers, and OnDetachingFrom detaches them. Because such a class usually saves some state, it generally
cannot be shared in a Style .
BehaviorEntryValidation sample is similar to TriggerEntryValidation except that it uses a behavior — the
NumericValidationBehavior class in the Xamarin.FormsBook.Toolkit library.

Behaviors with properties


Behavior<T> derives from Behavior , which derives from BindableObject , so bindable properties can be defined
on a behavior. These properties can be active in data bindings.
This is demonstrated in the EmailValidationDemo program that makes use of the ValidEmailBehavior class in
the Xamarin.FormsBook.Toolkit library. ValidEmailBehavior has a read-only bindable property and serves as a
source in data bindings.
The EmailValidationConv sample uses this same behavior to display another type of indicator to signal that an
email address is valid.
The EmailValidationTrigger sample is a variation on the previous sample. ButtonGlide uses a DataTrigger in
combination with that behavior.
Toggles and check boxes
It's possible to encapsulate the behavior of a toggle button in a class such as ToggleBehavior in the
Xamarin.FormsBook.Toolkit library, and then define all the visuals for the toggle entirely in XAML.
The ToggleLabel sample uses the ToggleBehavior with a DataTrigger to use a Label with two text strings for
the toggle.
The FormattedTextToggle sample extends this concept by switching between two FormattedString objects.
The ToggleBase class in the Xamarin.FormsBook.Toolkit library derives from ContentView , defines an
IsToggled property, and incorporates a ToggleBehavior for the toggle logic. This makes it easier to define the
toggle button in XAML, as demonstrated by the TraditionalCheckBox sample.
The SwitchCloneDemo includes a SwitchClone class that derives from ToggleBase and uses a TranslateAction
class to construct a toggle button that resembles the Xamarin.Forms Switch .
A RotateAction in the Xamarin.FormsBook.Toolkit provides an animation used to make an animated lever in
the LeverToggle sample.
Responding to taps
One drawback of EventTrigger is that you can't attach it to a TapGestureRecognizer to respond to taps. Getting
around that problem is the purpose of TapBehavior in the Xamarin.FormsBook.Toolkit
The BoxViewTapShiver sample uses TapBehavior to use the earlier ShiverAction for tapped BoxView elements.
The ShiverViews sample shows how to cut down on the markup by encapsulating a ShiverView class.
Radio buttons
The Xamarin.FormsBook.Toolkit library also has a RadioBehavior class for making radio buttons that are
grouped by a string group name.
The RadioLabels program uses text strings for its radio button. The RadioStyle sample uses a Style for the
difference in appearance between checked and unchecked buttons. The RadioImages sample uses boxed images
for its radio buttons:
The TraditionalRadios sample draws traditional appearing radio buttons with a dot inside a circle.
Fades and orientation
The final sample, MultiColorSliders allows you to switch between three different color-selection views using
radio buttons. The three views fade in and out using a FadeEnableAction in the Xamarin.FormsBook.Toolkit
library.
The program also responds to changes in orientation between portrait and landscape using a
GridOrientationBehavior in the Xamarin.FormsBook.Toolkit library.

Related links
Chapter 23 full text (PDF )
Chapter 23 samples
Working with Triggers
Xamarin.Forms Behaviors
Summary of Chapter 24. Page navigation
5/20/2019 • 8 minutes to read • Edit Online

Download the sample


Many applications consist of multiple pages among which the user navigates. The application always has a main
page or home page, and from there the user navigates to other pages, which are maintained in a stack for
navigating back. Additional navigation options are covered in Chapter 25. Page Varieties.

Modal pages and modeless pages


VisualElement defines a Navigation property of type INavigation , which includes the following two methods to
navigate to a new page:
PushAsync
PushModalAsync

Both methods accept a Page instance as an argument and return a Task object. The following two methods
navigate back to the previous page:
PopAsync
PopModalAsync

If the user interface has its own Back button (as Android and Windows phones do) then it's not necessary for the
application to call these methods.
Although these methods are available from any VisualElement , generally they are called from the Navigation
property of the current Page instance.
Applications generally use modal pages when the user is required to supply some information on the page before
returning to the previous page. Pages that are not modal are sometimes called modeless or hierarchical. Nothing
in the page itself distinguishes it as modal or modeless; it's governed instead by the method used to navigate to it.
To work across all platforms, a modal page must provide its own user interface for navigating back to the previous
page.
The ModelessAndModal sample allows you to explore the difference between modeless and modal pages. Any
application that uses page navigation must pass its home page to the NavigationPage constructor, generally in the
program's App class. One bonus is that you no longer need to set a Padding on the page for iOS.
You will discover that for modeless pages, the page's Title property is displayed. The iOS, Android, and the
Windows tablet and desktop platforms all provide a user-interface element to navigate back to the previous page.
Of course, Android, and Windows phone devices have a standard Back button to go back.
For modal pages, the page Title is not displayed, and no user-interface element is provided to go back to the
previous page. Although you can use the Android and Windows phone standard Back button to return to the
previous page, the modal page on the other platforms must provide its own mechanism to go back.
Animated page transitions
Alternative versions of the various navigation methods are provided with a second Boolean argument that you set
to true if you want the page transition to include an animation:
PushAsync
PushModalAsync
PopAsync
PopModalAsync
However, the standard page-navigation methods include the animation by default, so these are only valuable for
navigating to a particular page on startup (as discussed towards the end of this chapter) or when providing your
own entrance animation (as discussed in Chapter22. Animation).
Visual and functional variations
NavigationPage includes two properties that you can set when you instantiate the class in your App method:
BarBackgroundColor
BarTextColor

NavigationPage also includes four attached bindable properties that affect the particular page on which they are
set:
SetHasBackButton and GetHasBackButton
SetHasNavigationBar and GetHasNavigationBar
SetBackButtonTitle and GetBackButtonTitle work on iOS only
SetTitleIcon and GetTitleIcon work on iOS and Android only

Exploring the mechanics


The page navigation methods are all asynchronous and should be used with await . The completion doesn't
indicate that page navigation has completed, but only that it's safe to examine the page-navigation stack.
When one page navigates to another, the first page generally gets a call to its OnDisappearing method, and the
second page gets a call to its OnAppearing method. Similarly, when one page returns to another, the first page gets
a call to its OnDisappearing method, and the second page generally gets a call to its OnAppearing method. The
order of these calls (and the completion of the asynchronous methods that invokes the navigation) is platform
dependent. The use of the word "generally" in the two preceding statements is due to Android modal-page
navigation, in which these method calls don't occur.
Also, calls to the OnAppearing and OnDisappearing methods don't necessarily indicate page navigation.
The INavigation interface includes two collection properties that allow you to examine the navigation stack:
NavigationStack of type IReadOnlyList<Page> for the modeless stack
ModalStack of type IReadOnlyList<Page> for the modal stack

It is safest to access these stacks from the Navigation property of the NavigationPage (which should be the App
class's MainPage property). It is only safe to examine these stacks after the asynchronous page-navigation methods
have completed. The CurrentPage property of the NavigationPage does not indicate the current page if the current
page is a modal page, but indicates instead the last modeless page.
The SinglePageNavigation sample lets you explore page navigation and the stacks, and the legal types of page
navigations:
A modeless page can navigate to another modeless page or a modal page
A modal page can navigate only to another modal page
Enforcing modality
An application uses a modal page when it's necessary to obtain some information from the user. The user should
be prohibited from returning to the previous page until that information is provided. On iOS, it's easy to provide a
Back button and enable it only when the user has finished with the page. But for Android and Windows phone
devices, the application should override the OnBackButtonPressed method and return true if program has handled
the Back button itself, as demonstrated in the ModalEnforcement sample.
The MvvmEnforcement sample demonstrates how this works in an MVVM scenario.

Navigation variations
If a particular modal page can be navigated to multiple times, it should retain information so that the user can edit
the information rather than typing it all in again. You can handle this by retaining the particular instance of the
modal page, but a better approach (particularly on iOS ) is preserving the information in a view model.
Making a navigation menu
The ViewGalleryType sample demonstrates using a TableView to list menu items. Each item is associated with a
Type object for a particular page. When that item is selected, the program instantiates the page and navigates to it.

The ViewGalleryInst sample is a little different in that the menu contains instances of each page rather than
types. This helps retain the information from each page, but all the pages must be instantiated at program startup.
Manipulating the navigation stack
StackManipulation demonstrates several functions defined by INavigation that let you manipulate the
navigation stack in a structured manner:
RemovePage
InsertPageBefore
PopToRootAsync and PopToRootAsync with optional animation
Dynamic page generation
The BuildAPage sample demonstrates constructing a page at runtime based on user input.

Patterns of data transfer


It is often necessary to share data between pages — to transfer data to a navigated page, and for a page to return
data to the page that invoked it. There are several techniques for doing this.
Constructor arguments
When navigating to a new page, it's possible to instantiate the page class with a constructor argument that allows
the page to initialize itself. The SchoolAndStudents sample demonstrates this. It's also possible for the navigated
page to have its BindingContext set by the page that navigates to it.
Properties and method calls
The remaining data transfer examples explore the problem of passing information between pages when one page
navigates to another page and back. In these discussions, the home page navigates to the info page, and must
transfer initialized information to the info page. The info page obtains additional information from the user and
transfers the information to the home page.
The home page can easily access public methods and properties in the info page as soon as it instantiates that
page. The info page can also access public methods and properties in the home page, but choosing a good time for
this can be tricky. The DateTransfer1 sample does this in its OnDisappearing override. One drawback is that the
info page needs to know the type of the home page.
MessagingCenter
The Xamarin.Forms MessagingCenter class provides another way for two pages to communicate with each other.
Messages are identified by a text string and can be accompanied by any object.
A program that wishes to receive messages from a particular type must subscribe to them using
MessagingCenter.Subscribe and specify a callback function. Later it can unsubscribe by calling
MessagingCenter.Unsubscribe . The callback function receives any message sent from the specified type with the
specified name sent through the Send method.
The DateTransfer2 program demonstrates how to transfer data using the messaging center, but again this
requires that the info page know the type of the home page.
Events
The event is a time-honored approach for one class to send information to another class without knowing that
class's type. In the DateTransfer3 sample the info class defines an event that it fires when the information is ready.
However, there is no convenient place for the home page to detach the event handler.
The App class intermediary
The DateTransfer4 sample shows how to access properties defined in the App class by both the home page and
the info page. This is a good solution, but the next section describes something better.
Switching to a ViewModel
Using a ViewModel for the information allows the home page and the info page to share the instance of the
information class. This is demonstrated in the DateTransfer5 sample.
Saving and restoring page state
The App class intermediary or the ViewModel approach is ideal when the application must save information if the
program goes to sleep while the info page is active. The DateTransfer6 sample demonstrates this.

Saving and restoring the navigation stack


In the general case, a multipage program that goes to sleep should navigate to the same page when it is restored.
This means that such a program should save the contents of the navigation stack. This section shows how to
automate this process in a class designed for this purpose. This class also calls the individual pages to allow them
to save and restore their page state.
The Xamarin.FormsBook.Toolkit library defines an interface named IPersistantPage that classes can implement
to save and restore items in the Properties dictionary.
The MultiPageRestorableApp class in the Xamarin.FormsBook.Toolkit library derives from Application . You can
then derive your App class from MultiPageRestorableApp and perform some housekeeping.
The StackRestoreDemo demonstrates the use of MultiPageRestorableApp .
Something like a real-life app
The NoteTaker sample also makes use of MultiPageRestorableApp and allows for the entering and editing of notes
that are saved in the Properties dictionary.

Related links
Chapter 24 full text (PDF )
Chapter 24 samples
Hierarchical Navigation
Modal Pages
Summary of Chapter 25. Page varieties
12/7/2018 • 4 minutes to read • Edit Online

Download the sample


So far you've seen two classes that derive from Page : ContentPage and NavigationPage . This chapter presents two
others:
MasterDetailPage manages two pages, a master and a detail
TabbedPage manages multiple child pages accessed through tabs
These page types provide more sophisticated navigation options than the NavagationPage discussed in Chapter 24.
Page Navigation.

Master and Detail


The MasterDetailPage defines two properties of type Page : Master and Detail . Generally you set each of these
properties to a ContentPage . The MasterDetailPage displays and switches between these two pages.
There are two fundamental ways to switch between these two pages:
split where the master and detail are side by side
popover where the detail page covers or partially covers the master page
There are several variations of the popover approach (slide, overlap, and swap), but these are generally platform
dependent. You can set the MasterDetailBehavior property of MasterDetailPage to a member of the
MasterBehavior enumeration:

Default
Split
SplitOnLandscape
SplitOnPortrait
Popover

However, this property has no effect on phones. Phones always have a popover behavior. Only tablets and desktop
windows can have a split behavior.
Exploring the Behaviors
The MasterDetailBehaviors sample allows you to experiment with the default behavior on different devices. The
program contains two separate ContentPage derivatives for the master and detail (with a Title property set on
both), and another class that derives from MasterDetailPage that combines them. The detail page is enclosed in a
NavigationPage because the UWP program wouldn't work without it.

The Windows 8.1 and Windows Phone 8.1 platforms require that a bitmap be set to the Icon property of the
master page.
Back to School
The SchoolAndDetail sample takes a somewhat different approach to constructing the program to display
students from the SchoolOfFineArt library.
The Master and Detail properties are defined with visual trees in the SchoolAndDetailPage.xaml file, which
derives from MasterDetailPage . This arrangement allows data bindings to be set between the master and detail
pages.
That XAML file also sets the IsPresented property of MasterDetailPage to True . This causes the master page to
be displayed at startup; by default the detail page is displayed. The SchoolAndDetailPage.xaml.cs file sets
IsPresented to false when an item is selected from the ListView in the master page. The detail page is then
displayed:

Your own user interface


Although Xamarin.Forms provides a user interface for switching between the master and detail views, you can
supply your own. To do so:
Set the IsGestureEnabled property to false to disable swiping
Override the ShouldShowToolbarButton method and return false to hide the toolbar buttons on Windows 8.1
and Windows Phone 8.1.
You must then provide a means to switch between the master and detail pages, such as demonstrated by the
ColorsDetail sample.
The MasterDetailTaps sample demonstrates another approach using a TapGestureRecognizer on the master and
detail pages.

TabbedPage
The TabbedPage is a collection of pages that you can switch among using tabs. It derives from MultiPage<Page>
and defines no public properties or methods of its own. MultiPage<T> , however, does define a property:
Children property of type IList<T>

You fill this Children collection with page objects.


Another approach allows you to define the TabbedPage children much like a ListView using these two properties
that generate the tabbed pages automatically:
ItemsSource of type IEnumerable
ItemTemplate of type DataTemplate

However, this approach does not work well on iOS when the collection contains more than a few items.
MultiPage<T> defines two more properties that let you keep track of which page is currently viewed:
CurrentPage of type T , referring to the page
SelectedItem of type Object , referring to the object in the ItemsSource collection
MultiPage<T> also defines two events:
PagesChanged when the ItemsSource collection changes
CurrentPageChanged when the viewed page changes

Discrete tab pages


The DiscreteTabbedColors sample consists of three tabbed pages that display colors in three different ways. Each
tab is a ContentPage derivative, and then the TabbedPage derivative DiscreteTabbedColorsPage.xaml combines the
three pages.
For each page that appears in a TabbedPage , the Title property is required to specify the text in the tab, and the
Apple Store requires that an icon be used as well, so the Icon property is set for iOS:

The StudentNotes sample has a home page that lists all the students. When a student is tapped, this navigates to
a TabbedPage derivative, StudentNotesDataPage , that incorporates three ContentPage objects in its visual tree, one
of which allows entering some notes for that student.
Using an ItemTemplate
The MultiTabbedColor sample uses the NamedColor class in the Xamarin.FormsBook.Toolkit library. The
MultiTabbedColorsPage.xaml file sets the DataTemplate property of TabbedPage to a visual tree beginning with
ContentPage that contains bindings to properties of NamedColor (including a binding to the Title property).

However, this is problematic on iOS. Only a few of the items can be displayed, and there is no good way to give
them icons.

Related links
Chapter 25 full text (PDF )
Chapter 25 samples
Master-Detail Page
Tabbed Page
Summary of Chapter 26. Custom layouts
12/7/2018 • 7 minutes to read • Edit Online

Download the sample


Xamarin.Forms includes several classes derived from Layout<View> :
StackLayout ,
Grid ,
AbsoluteLayout , and
RelativeLayout .

This chapter describes how to create your own classes that derive from Layout<View> .

An overview of layout
There is no centralized system that handles Xamarin.Forms layout. Each element is responsible for determining
what its own size should be, and how to render itself within a particular area.
Parents and children
Every element that has children is responsible for positioning those children within itself. It is the parent that
ultimately determines what size its children should be based on the size it has available and the size the child wants
to be.
Sizing and positioning
Layout begins at the top of the visual tree with the page and then proceeds through all the branches. The most
important public method in layout is Layout defined by VisualElement . Every element that is a parent to other
elements calls Layout for each of its children to give the child a size and postition relative to itself in the form of a
Rectangle value. These Layout calls propagate through the visual tree.

A call to Layout is required for an element to appear on the screen, and causes the following read-only properties
to be set. They are consistent with the Rectangle passed to the method:
Bounds of type Rectangle
X of type double
Y of type double
Width of type double
Height of type double

Prior to the Layout call, Height and Width have mock values of –1.
A call to Layout also triggers calls to the following protected methods:
SizeAllocated , which calls
OnSizeAllocated , which can be overridden.

Finally, the following event is fired:


SizeChanged

The OnSizeAllocated method is overridden by Page and Layout , which are the only two classes in
Xamarin.Forms that can have children. The overridden method calls
UpdateChildrenLayout for Page derivatives and UpdateChildrenLayout for Layout derivatives, which calls
LayoutChildren for Page derivatives and LayoutChildren for Layout derivatives.
LayoutChildren then calls Layout for each of the element's children. If at least one child has a new Bounds setting,
then the following event is fired:
LayoutChanged for Page derivatives and LayoutChanged for Layout derivatives
Constraints and size requests
For LayoutChildren to intelligently call Layout on all its children, it must know a preferred or desired size for the
children. Therefore the calls to Layout for each of the children are generally preceded by calls to
GetSizeRequest

After the book was published, the GetSizeRequest method was deprecated and replaced with
Measure

The Measure method accommodates the Margin property and includes an argument of type MeasureFlag , which
has two members:
IncludeMargins
None to not include margins
For many elements, GetSizeRequest or Measure obtains the native size of the element from its renderer. Both
methods have parameters for width and height constraints. For example, a Label will use the width constraint to
determine how to wrap multiple lines of text.
Both GetSizeRequest and Measure return a value of type SizeRequest , which has two properties:
Request of type Size
Minimum of type Size

Very often these two values are the same, and the Minimum value can usually be ignored.
VisualElement also defines a protected method similar to GetSizeRequest that is called from GetSizeRequest :
OnSizeRequest returns a SizeRequest value
That method is now deprecated and replaced with:
OnMeasure

Every class that derives from Layout or Layout<T> must override OnSizeRequest or OnMeasure . This is where a
layout class determines its own size, which is generally based on the size of its children, which it obtains by calling
GetSizeRequest or Measure on the children. Before and after calling OnSizeRequest or OnMeasure , GetSizeRequest
or Measure makes adjustments based on the following properties:
WidthRequest of type double , affects the Request property of SizeRequest
HeightRequest of type double , affects the Request property of SizeRequest
MinimumWidthRequest of type double , affects the Minimum property of SizeRequest
MinimumHeightRequest of type double , affects the Minimum property of SizeRequest

Infinite constraints
The constraint arguments passed to GetSizeRequest (or Measure ) and OnSizeRequest (or OnMeasure ) can be
infinite (i.e., values of Double.PositiveInfinity ). However, the SizeRequest returned from these methods cannot
contain infinite dimensions.
Infinite constraints indicate that the requested size should reflect the element's natural size. A vertical StackLayout
calls GetSizeRequest (or Measure ) on its children with an infinite height constraint. A horizontal stack layout calls
GetSizeRequest (or Measure ) on its children with an infinite width constraint. An AbsoluteLayout calls
GetSizeRequest (or Measure ) on its children with infinite width and height constraints.

Peeking inside the process


The ExploreChildSize displays constraint and size request information for a simple layout.

Deriving from Layout


A custom layout class derives from Layout<View> . It has two responsibilities:
Override OnMeasure to call Measure on all the layout's children. Return a requested size for the layout itself
Override LayoutChildren to call Layout on all the layout's children

The for or foreach loop in these overrides should skip any child whose IsVisible property is set to false .
A call to OnMeasure is not guaranteed. OnMeasure will not be called if the parent of the layout is governing the
layout's size (for example, a layout that fills a page). For this reason, LayoutChildren cannot rely on child sizes
obtained during the OnMeasure call. Very often, LayoutChildren must itself call Measure on the layout's children, or
you can implement some kind of size caching logic (to be discussed later).
An easy example
The VerticalStackDemo sample contains a simplified VerticalStack class and a demonstration of its use.
Vertical and horizontal positioning simplified
One of the jobs that VerticalStack must perform occurs during the LayoutChildren override. The method uses
the child's HorizontalOptions property to determine how to position the child within its slot in the VerticalStack .
You can instead call the static method Layout.LayoutChildIntoBoundingRect . This method calls Measure on the child
and uses its HorizontalOptions and VerticalOptions properties to position the child within the specified rectangle.
Invalidation
Often a change in an element's property affects how that element appears in layout. The layout must be
invalidated to trigger a new layout.
VisualElement defines a protected method InvalidateMeasure , which is generally called by the property-changed
handler of any bindable property whose change affects the element's size. The InvalidateMeasure method fires a
MeasureInvalidated event.

The Layout class defines a similar protected method named InvalidateLayout , which a Layout derivative should
call for any change that affects how it positions and sizes its children.
Some rules for coding layouts
1. Properties defined by Layout<T> derivatives should be backed by bindable properties, and the property-
changed handlers should call InvalidateLayout .
2. A Layout<T> derivative that defines attached bindable properties should override OnAdded to add a
property-changed handler to its children and OnRemoved to remove that handler. The handler should check
for changes in these attached bindable properties and respond by calling InvalidateLayout .
3. A Layout<T> derivative that implements a cache of child sizes should override InvalidateLayout and
OnChildMeasureInvalidated and clear the cache when these methods are called.

A layout with properties


The WrapLayout class in the Xamarin.FormsBook.Toolkit assumes that all its children are the same size, and
wraps the children from one row (or column) to the next. It defines an Orientation property like StackLayout , and
ColumnSpacing and RowSpacing properties like Grid , and it caches child sizes.

The PhotoWrap sample puts a WrapLayout in a ScrollView for displaying stock photos.
No unconstrained dimensions allowed!
The UniformGridLayout in the Xamarin.FormsBook.Toolkit library is intended to display all its children within
itself. Therefore, it cannot deal with unconstrained dimensions and raises an exception if one is encountered.
The PhotoGrid sample demonstrates UniformGridLayout :

Overlapping children
A Layout<T> derivative can overlap its children. However, the children are rendered in their order in the Children
collection, and not the order in which their Layout methods are called.
The Layout class defines two methods that allow you to move a child within the collection:
LowerChild to move a child to the beginning of the collection
RaiseChild to move a child to the end of the collection

For overlapping children, children at the end of the collection visually appear on top of children at the beginning of
the collection.
The OverlapLayout class in the Xamarin.FormsBook.Toolkit library defines an attached property to indicate the
render order and thus allow one of its children to be displayed on top of the others. The StudentCardFile sample
demonstrates this:
More attached bindable properties
The CartesianLayout class in the Xamarin.FormsBook.Toolkit library defines attached bindable properties to
specify two Point values and a thickness value and manipulates BoxView elements to resemble lines.
The UnitCube sample uses that to draw a 3D cube.
Layout and LayoutTo
A Layout<T> derivative can call LayoutTo rather than Layout to animate the layout. The AnimatedCartesianLayout
class does this, and the AnimatedUnitCube sample demonstrates it.

Related links
Chapter 26 full text (PDF )
Chapter 26 samples
Creating Custom Layouts
Summary of Chapter 27. Custom renderers
1/29/2019 • 3 minutes to read • Edit Online

Download the sample

NOTE
Notes on this page indicate areas where Xamarin.Forms has diverged from the material presented in the book.

A Xamarin.Forms element such as Button is rendered with a platform-specific button encapsulated in a class
named ButtonRenderer . Here is the iOS version of ButtonRenderer , the Android version of ButtonRenderer , and
the UWP version of ButtonRenderer .
This chapter discusses how you can write your own renderers to create custom views that map to platform-specific
objects.

The complete class hierarchy


There are four assemblies that contain the Xamarin.Forms platform-specific code. You can view the source on
GitHub using these links:
Xamarin.Forms.Platform (very small)
Xamarin.Forms.Platform.iOS
Xamarin.Forms.Platform.Android
Xamarin.Forms.Platform.UAP

NOTE
The WinRT assemblies mentioned in the book are no longer part of this solution.

The PlatformClassHierarchy sample displays a class hierarchy for the assemblies that are valid for the executing
platform.
You'll notice an important class named ViewRenderer . This is the class you derive from when creating a platform-
specific renderer. It exists in three different versions, because it's tied to the view system of the target platform:
The iOS ViewRenderer<TView, TNativeView> has generic arguments:
TView constrained to Xamarin.Forms.View
TNativeView constrained to UIKit.UIView

The Android ViewRenderer<TView, TNativeView> has generic arguments:


TView constrained to Xamarin.Forms.View
TNativeView constrained to Android.Views.View

The UWP ViewRenderer<TElement, TNativeElement> has differently named generic arguments:


TElement constrained to Xamarin.Forms.View
TNativeElement constrained to Windows.UI.Xaml.FrameworkElement
When writing a renderer, you will be deriving a class from View , and then writing multiple ViewRenderer classes,
one for each supported platform. Each platform-specific implementation will reference a native class that derives
from the type you specify as the TNativeView or TNativeElement parameter.

Hello, custom renderers!


The HelloRenderers program references a custom view named HelloView in its App class.
The HelloView class is included in the HelloRenderers project and simply derives from View .
The HelloViewRenderer class in the HelloRenderers.iOS project derives from ViewRenderer<HelloView, UILabel> .
In the OnElementChanged override, it creates a native iOS UILabel and calls SetNativeControl .
The class in the HelloRenderers.Droid project derives from
HelloViewRenderer
ViewRenderer<HelloView, TextView> . In the OnElementChanged override, it creates an Android TextView and calls
SetNativeControl .

The class in the HelloRenderers.UWP and other Windows projects derives from
HelloViewRenderer
ViewRenderer<HelloView, TextBlock> . In the OnElementChanged override, it creates a Windows TextBlock and calls
SetNativeControl .

All the ViewRendererderivatives contain an ExportRenderer attribute on the assembly level that associates the
HelloView class with the particular HelloViewRenderer class. This is how Xamarin.Forms locates renderers in the
individual platform projects:

Renderers and properties


The next set of renderers implements ellipse drawing, and is located in the various projects of the
Xamarin.FormsBook.Platform solution.
The EllipseView class is in the Xamarin.FormsBook.Platform platform. The class is similar to BoxView and
defines just a single property: Color of type Color .
The renderers can transfer property values set on a View to the native object by overriding the
OnElementPropertyChanged method in the renderer. Within this method (and within most of the renderer ), two
properties are available:
Element , the Xamarin.Forms element
Control , the native view or widget or control object
The types of these properties are determined by the generic parameters to ViewRenderer . In this example, Element
is of type EllipseView .
The OnElementPropertyChanged override can therefore transfer the Color value of the Element to the native
Control object, probably with some kind of conversion. The three renderers are:
iOS: EllipseViewRenderer , which uses an EllipseUIView class for the ellipse.
Android: EllipseViewRenderer , which uses an EllipseDrawableView class for the ellipse.
UWP: EllipseViewRenderer , which can use the native Windows Ellipse class.

The EllipseDemo class displays several of these EllipseView objects:

The BouncingBall bounces an EllipseView off the sides of the screen.

Renderers and events


It is also possible for renderers to indirectly generate events. The StepSlider class is similar to the normal
Xamarin.Forms Slider but allows specifying a number of discrete steps between the Minimum and Maximum
values.
The three renderers are:
iOS: StepSliderRenderer
Android: StepSliderRenderer
UWP: StepSliderRenderer

The renderers detect changes to the native control, and then call SetValueFromRenderer , which references a
bindable property defined in the StepSlider , a change to which causes the StepSlider to fire a ValueChanged
event.
The StepSliderDemo sample demonstrates this new slider.

Related links
Chapter 27 full text (PDF )
Chapter 27 samples
Custom Renderers
Summary of Chapter 28. Location and maps
4/2/2019 • 8 minutes to read • Edit Online

Download the sample

NOTE
Notes on this page indicate areas where Xamarin.Forms has diverged from the material presented in the book.

Xamarin.Forms supports a Map element that derives from View . Because of the special platform requirements
involved in using maps, they are implemented in a separate assembly, Xamarin.Forms.Maps, and involve a
different namespace: Xamarin.Forms.Maps .

The geographic coordinate system


A geographic coordinate system identifies positions on a spherical (or nearly spherical) object like the Earth. A
coordinate consists of both a latitude and longitude expressed in angles.
A great circle called the equator is midway between the two poles through which the Earth's axis conceptually
extends.
Parallels and latitude
An angle measured north or south of the equator from the center of the Earth marks lines of equal latitude known
as parallels. These range from 0 degrees at the equator to 90 degrees at the north and south poles. By convention,
latitudes north of the equator are positive values, and those south of the equator are negative values.
Longitude and meridians
Halves of great circles from the north pole to the south pole are lines of equal longitude, also known as meridians.
These are relative to the Prime Meridian in Greenwich, England. By convention, longitudes east of the Prime
Meridian are positive values from 0 degrees to 180 degrees, and longitudes west of the Prime Meridian are
negative values from 0 degrees to –180 degrees.
The equirectangular projection
Any flat map of the Earth introduces distortions. If all the lines of latitude and longitude are straight, and if equal
differences in latitude and longitude angles correspond to equal distances on the map, the result is an
equirectangular projection. This map distorts areas closer to the poles because they are horizontally stretched out.
The Mercator projection
The popular Mercator projection attempts to compensate for the horizontal stretching by also stretching these
areas vertically. This results in a map where areas near the poles appear much larger than they really are, but any
local area conforms quite closely with the actual area.
Map services and tiles
Map services use a variation of the Mercator projection called Web Mercator . The map services deliver bitmap tiles
to a client based on location and zoom level.

Getting the user's location


The Xamarin.Forms Map classes do not include a facility to obtain the user's geographic location, but this is often
desirable when working with maps, so a dependency service must handle it.
NOTE
Xamarin.Forms applications can instead use the Geolocation class included in Xamarin.Essentials.

The location tracker API


The Xamarin.FormsBook.Platform solution contains code for a location tracker API. The GeographicLocation
structure encapsulates a latitude and longitude. The ILocationTracker interface defines two methods to start and
pause the location tracker, and an event when a new location is available.
The iOS location manager
The iOS implementation of ILocationTracker is a LocationTracker class that makes use of the iOS
CLLocationManager .

The Android location manager


The Android implementation of ILocationTracker is a LocationTracker class that makes use of the Android
LocationManager class.

The UWP geo locator


The Universal Windows Platform implementation of ILocationTracker is a LocationTracker class that makes use
of the UWP Geolocator .
Display the phone's location
The WhereAmI sample uses the location tracker to display the phone's location, both in text and on a
equirectangular map.
The required overhead
Some overhead is required for WhereAmI to use the location tracker. First, all of the projects in the WhereAmI
solution must have references to the corresponding projects in Xamarin.FormsBook.Platform, and each
WhereAmI project must call the Toolkit.Init method.
Some additional platform-specific overhead, in the form of location permissions, is required.
Location permission for iOS
For iOS, the info.plist file must include items containing the text of a question asking the user to allow getting that
user's location.
Location permissions for Android
Android applications that obtain the user's location must have an ACCESS_FILE_LOCATION permission in the
AndroidManifest.xml file.
Location permissions for the UWP
A Universal Windows Platform application must have a location device capability marked in the
Package.appxmanifest file.

Working with Xamarin.Forms.Maps


Several requirements are involved in using the Map class.
The NuGet package
The Xamarin.Forms.Maps NuGet library must be added to the application solution. The version number should
be the same as the Xamarin.Forms package currently installed.
Initializing the Maps package
The application projects must call the Xamarin.FormsMaps.Init method after making a call to
Xamarin.Forms.Forms.Init .
Enabling map services
Because the Map can obtain the user's location, the application must obtain permission for the user in the manner
described earlier in this chapter:
Enabling iOS maps
An iOS application using Map needs two lines in the info.plist file.
Enabling Android maps
An authorization key is required for using Google Map services. This key is inserted in the AndroidManifest.xml
file. In addition, the AndroidManifest.xml file requires manifest tags involved in obtaining the user's location.
Enabling UWP maps
A Universal Windows Platform application requires an authorization key for using Bing Maps. This key is passed
as an argument to the Xamarin.FormsMaps.Init method. The application must also be enabled for location services.
The unadorned map
The MapDemos sample consists of a MapsDemoHomePage.xaml file and MapsDemoHomePage.xaml.cs code-
behind file that allows navigating to various demonstration programs.
The BasicMapPage.xaml file shows how to display the Map view. By default it displays the city of Rome, but the
map can be manipulated by the user.
To disable horizontal and vertical scrolling, set the HasScrollEnabled property to false . To disable zooming, set
HasZoomEnabled to false . These properties might not work on all platforms.

Streets and Terrain


You can display different types of maps by setting the Map property MapType of type MapType , an enumeration
with three members:
Street , the default
Satellite
Hybrid

The MapTypesPage.xaml file shows how to use a radio button to select the map type. It makes use of the
RadioButtonManager class in the Xamarin.FormsBook.Toolkit library and a class based on the
MapTypeRadioButton.xaml file.
Map coordinates
A program can obtain the current area that the Map is displaying through the VisibleRegion property. This
property is not backed by a bindable property, and there is no notification mechanism to indicate when it has
changed, so a program that wishes to monitor the property should probably use a timer for that purpose.
VisibleRegion is of type MapSpan , a class with four read-only properties:
Center of type Position
LatitudeDegrees of type double , indicating the height of the displayed area of the map
LongitudeDegrees of type double , indicating the width of the displayed area of the map
Radius of type Distance , indicating the size of the largest circular area visible on the map

Position and Distance are both structures. Position defines two read-only properties set via the Position
constructor:
Latitude
Longitude

Distance is intended to provide a unit-independent distance by converting between metric and English units. A
Distance value can be created in several ways:
Distance constructor with a distance in meters
Distance.FromMeters static method
Distance.FromKilometers static method
Distance.FromMiles static method

The value is available from three properties:


Meters of type double
Kilometers of type double
Miles of type double

The MapCoordinatesPage.xaml file contains several Label elements for displaying the MapSpan information. The
MapCoordinatesPage.xaml.cs code-behind file uses a timer to keep the information updated as the user
manipulates the map.
Position extensions
A new library for this book named Xamarin.FormsBook.Toolkit.Maps contains map-specific but platform-
independent types. The PositionExtensions class has a ToString method for Position , and a method to calculate
the distance between two Position values.
Setting an initial location
You can call the MoveToRegion method of Map to programmatically set a location and zoom level on the map. The
argument is of type MapSpan . You can create a MapSpan object using either of the following:
MapSpan constructor with a Position , and latitude and longitude span
MapSpan.FromCenterAndRadius with a Position and radius

It's also possible to create a new MapSpan from an existing one using the methods ClampLatitude or WithZoom .
The WyomingPage.xaml file and WyomingPage.xaml.cs code-behind file demonstrates how to use the
MoveToRegion method to display the state of Wyoming.

You can alternatively use the Map constructor with a MapSpan object to initialize the location of the map. The
XamarinHQPage.xaml file shows how to do this entirely in XAML to display Xamarin's headquarters in San
Francisco.
Dynamic zooming
You can use a Slider to dynamically zoom a map. The RadiusZoomPage.xaml file and RadiusZoomPage.xaml.cs
code-behind file show how to change the radius of a map based on the Slider value.
The LongitudeZoomPage.xaml file and LongitudeZoomPage.xaml.cs code-behind file show an alternative
approach that works better on Android, but neither approach works well on the Windows platforms.
The Phone's location
The IsShowingUser property of Map works a little differently on each platform as the ShowLocationPage.xaml file
demonstrates:
On iOS, a blue dot indicates the phone's location but you must manually navigate there
On Android, an icon is displayed that when pushed moves the map to the phone's location
The UWP is similar to iOS but sometimes automatically navigates to the location
The MapDemos project attempts to mimic the Android approach by first defining an icon-based button based on
the MyLocationButton.xaml file and MyLocationButton.xaml.cs code-behind file.
The GoToLocationPage.xaml file and GoToLocationPage.xaml.cs code-behind file use this button to navigate to the
phone's location.
Pins and science museums
Finally, the Map class defines a Pins property of type IList<Pin> . The Pin class defines four properties:
Label of type string , a required property
Address of type string , an optional human-readable address
Position of type Position , indicating where the pin is displayed on the map
Type of type PinType , an enumeration, which is not used

The MapDemos project contains the file ScienceMuseums.xml, which lists science museums in the United States,
and Locations and Site classes for deserializing this data.
The ScienceMuseumsPage.xaml file and ScienceMuseumsPage.xaml.cs code-behind file display pins for these
science museums in the map. When the user taps a pin, it displays the address and a website for the museum.
The distance between two points
The PositionExtensions class contains a DistanceTo method with a simplified calculation of the distance between
two geographic locations.
This is used in the LocalMuseumsPage.xaml file and LocalMuseumsPage.xaml.cs code-behind file to also display
the distance to the museum from the user's location:

The program also demonstrates how to dynamically restrict the number of pins based on the location of the map.

Geocoding and back again


The Xamarin.Forms.Maps assembly also contains a Geocoder class with a GetPositionsForAddressAsync method
that converts a text address into zero or more possible geographic positions, and another method
GetAddressesForPositionAsync that converts in the other direction.

The GeocoderRoundTrip.xaml file and GeocoderRoundTrip.xaml.cs code-behind file demonstrate this facility.

Related links
Chapter 28 full text (PDF )
Chapter 28 samples
Xamarin.Forms Map

S-ar putea să vă placă și