PROWAREtech
Xamarin: Tutorial - Page 02
StackLayout
Because Xamarin cannot have more than a single widget/control per ContentPage
, another element is needed: the StackLayout
.
With this it is possible to have multiple children in place. Notice the BackgroundColor
attribute of the ContentPage
element which changes the color of the screen and Slider
is a widget/control.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloXamarinForms"
x:Class="HelloXamarinForms.MainPageXaml"
BackgroundColor="#CCCCCC">
<StackLayout VerticalOptions="Center" HorizontalOptions="Center">
<Button Text="Click Here!" Clicked="Button_Clicked" />
<Slider />
</StackLayout>
</ContentPage>
Now, have the Slider
change the opacity of the button. Add a ValueChanged="Slider_Changed"
attribute to the
Slider
and give the Button
a name using the x:Name
attribute. This allows the C# code to access it.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloXamarinForms"
x:Class="HelloXamarinForms.MainPageXaml">
<StackLayout VerticalOptions="Center" HorizontalOptions="Center">
<Button x:Name="bttn" Text="Click Here!" Opacity="1" Clicked="Button_Clicked" />
<Slider ValueChanged="Slider_Changed" />
</StackLayout>
</ContentPage>
using Xamarin.Forms;
namespace HelloXamarinForms
{
public partial class MainPageXaml : ContentPage
{
public MainPageXaml()
{
InitializeComponent();
}
void Button_Clicked(object sender, System.EventArgs e)
{
DisplayAlert("Xamarin Forms", "Hello Xamarin Forms!", "OK");
((Button)sender).Text = "Clicked!";
}
void Slider_Changed(object sender, ValueChangedEventArgs e)
{
bttn.Opacity = e.NewValue;
}
}
}
Data Binding
Through data binding, more can be done in XAML and less coding is needed. It always has a source and a target. The source is a property of an object that changes dynamically at run time. When the property changes, the data binding updates the target (a property of another object).
The source must implement the INotifyPropertyChanged
interface and all the visual elements in
Xamarin.Forms implements this inteface via BindableObject
. INotifyPropertyChanged
is covered in greater depth later in this tutorial. The bottom line is that data bindings can be created
between the visual objects (widgets/controls) and properties.
To set up data binding in XAML:
-
Set
BindingContext
of the target element (theButton
) tox:Reference
referencing the source element (Slider
). -
Set the target property (the
Opacity
property of theButton
) to reference the source property (theValue
property of theSlider
).
Example Code
This code continues from the previous section.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloXamarinForms"
x:Class="HelloXamarinForms.MainPageXaml">
<StackLayout VerticalOptions="Center" HorizontalOptions="Center">
<Button Text="Click Here!"
BindingContext="{x:Reference Name=sldr}"
Opacity="{Binding Path=Value}"
Clicked="Button_Clicked" />
<Slider x:Name="sldr" />
</StackLayout>
</ContentPage>
Remove the Slider_Changed()
method from the C# code.
public partial class MainPageXaml : ContentPage
{
public MainPageXaml()
{
InitializeComponent();
}
void Button_Clicked(object sender, System.EventArgs e)
{
DisplayAlert("Xamarin Forms", "Hello Xamarin Forms!", "OK");
((Button)sender).Text = "Clicked!";
}
/*
void Slider_Changed(object sender, ValueChangedEventArgs e)
{
bttn.Opacity = e.NewValue;
}
//*/
}
The XAML file can be rewritten to do the same thing.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloXamarinForms"
x:Class="HelloXamarinForms.MainPageXaml">
<StackLayout VerticalOptions="Center" HorizontalOptions="Center">
<Button Text="Click Here!"
Opacity="{Binding Source={x:Reference sldr}, Path=Value}"
Clicked="Button_Clicked" />
<Slider x:Name="sldr" />
</StackLayout>
</ContentPage>
Adding a BoxView
and having its opacity change is now very a simple procedure. The BoxView
is very simple
and is explained later.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloXamarinForms"
x:Class="HelloXamarinForms.MainPageXaml">
<StackLayout VerticalOptions="Center" HorizontalOptions="Center">
<Button Text="Click Here!"
Opacity="{Binding Source={x:Reference sldr}, Path=Value}"
Clicked="Button_Clicked" />
<BoxView Color="Blue"
Opacity="{Binding Source={x:Reference sldr}, Path=Value}" />
<Slider x:Name="sldr" />
</StackLayout>
</ContentPage>
It is possible to clean up the XAML even more by adding a BindingContext
attribute (property) to the
StackLayout
and all the child elements inherit it. Now notice the Opacity
attributes.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloXamarinForms"
x:Class="HelloXamarinForms.MainPageXaml">
<StackLayout BindingContext="{x:Reference sldr}"
VerticalOptions="Center"
HorizontalOptions="Center">
<Button Text="Click Here!"
Opacity="{Binding Value}"
Clicked="Button_Clicked" />
<BoxView Color="Blue"
Opacity="{Binding Value}" />
<Slider x:Name="sldr" />
</StackLayout>
</ContentPage>
The Page
has a BindingContext
property, too.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloXamarinForms"
x:Class="HelloXamarinForms.MainPageXaml"
BindingContext="{x:Reference sldr}">
<StackLayout VerticalOptions="Center"
HorizontalOptions="Center">
<Button Text="Click Here!"
Opacity="{Binding Value}"
Clicked="Button_Clicked" />
<BoxView Color="Blue"
Opacity="{Binding Value}" />
<Slider x:Name="sldr" />
</StackLayout>
</ContentPage>