Documente Academic
Documente Profesional
Documente Cultură
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.
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
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.
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.
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
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.
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.
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.
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 :
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
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.
Several instance methods allow modifying an existing color to create a new color:
AddLuminosity
MultiplyAlpha
WithHue
WithLuminosity
WithSaturation
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.
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
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.
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.
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
NOTE
Notes on this page indicate areas where Xamarin.Forms has diverged from the material presented in the book.
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.
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.
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
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 .
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
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.
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.
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.
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
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
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
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.
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.
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
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
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.
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
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
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"
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
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
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.
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.
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.
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
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:
Boolean Switch
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)
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 .
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 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
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
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
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 .
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 .
Properties that are likely to be the targets of data bindings in MVVM scenarios generally have a
DefaultBindingMode of TwoWay . These are:
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.
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.
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
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 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.
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
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.
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.
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
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.
NOTE
The Xamarin.Forms Picker now includes ItemsSource and SelectedItem properties that support data binding. See
Picker.
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.
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 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
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
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.
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.
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.
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.
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.
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.
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:
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
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.
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 .
The MoreViewExtensions class contains a BezierPathTo extension method and a CancelBezierPathTo method.
The BezierLoop sample demonstrates animating an element along a Beizer path.
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.
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
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:
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.
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
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
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.
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
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:
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>
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
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
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.
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.
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.
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
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.
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 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:
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
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 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 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.
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