際際滷

際際滷Share a Scribd company logo
XAML Xamarin
XAML (eXtensible Application Markup Language)
XAML intro (1)
 XAML (eXtensible Application Markup Language) consente
agli sviluppatori di definire le interfacce utente nelle applicazioni
Xamarin.Forms tramite markup anzich辿 codice.
 XAML 竪 particolarmente adatto per l'uso con l'architettura
delle applicazioni MVVM (Model-View-ViewModel) pi湛 diffusi:
XAML definisce la vista collegata al ViewModel codice tramite
le associazioni di dati basati su XAML.
XAML intro (2)
 XAML 竪 un linguaggio basato su XML creato da
Microsoft come alternativa al codice di programmazione
per la creazione di istanze e inizializzazione di oggetti e
per organizzare gli oggetti nelle gerarchie padre-figlio.
 XAML fa parte di xamarin.Forms, al suo interno, lo
sviluppatore pu嘆 definire le interfacce utente: viste,
layout e pagine
C# e XAML (2)
Code
+ Markup
----------------------
Awesome Apps
C# e XAML (3)
 XAML 竪 un file xml
 Ogni elemento 竪 organizzato secondo una gerarchia padre
figlio
 Ogni elemento pu嘆 avere degli attributi
C# e XAML (1)
 C# 竪 un linguaggio Procedurale
 XAML 竪 un linguaggio dichiarativo
 C# definisce linterazione tra Oggetti UI
 XAML definisce gli oggetti che compongono UI
Esempio di XAML
1) <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
2) xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
3) x:Class="App1.MainPage">
4) <StackLayout>
5) <!-- Place new controls here -->
6) <Label Text="Welcome to Xamarin.Forms!"
7) HorizontalOptions="Center"
8) VerticalOptions="CenterAndExpand" />
9) <Button Text="Click ME!" HorizontalOptions="Center" />
10) <際際滷r VerticalOptions="CenterAndExpand" />
11) </StackLayout>
12) </ContentPage>
Xaml su Xamarin
XAML Namespaces (1)
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App1.MainPage">
<StackLayout>
<Label Text="Welcome to Xamarin.Forms!"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Button Text="Click ME!" HorizontalOptions="Center" />
<際際滷r VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
XAML Namespaces (2)
 xmlns="http://xamarin.com/schemas/2014/forms" include
le definizioni di xamarin.forms e definisce tutti gli elementi
senza prefisso (x) (es. ContentPage)
 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
include tutti i prefissi prefissi usati dichiarare spazi dei
nomi non predefiniti . Come x:Class che specifica il
nome della classe associata allo XAML nel code-
behind. Nel nostro caso App1.MainPage.
Classi ed elementi (1)
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App1.MainPage">
<StackLayout>
<Label Text="Welcome to Xamarin.Forms!"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Button Text="Click ME!" HorizontalOptions="Center" />
<際際滷r VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
Classi ed elementi (2)
 ContentPage, StackLayout, Label, Button e 際際滷r sono
elementi xml che diventano classi C# nel code-behind e
vengono chiamati Object Elements
Attributi (1)
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App1.MainPage">
<StackLayout>
<Label Text="Welcome to Xamarin.Forms!"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Button Text="Click ME!" HorizontalOptions="Center" />
<際際滷r VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
Attributi (2)
 Text, FontSize, VerticalOptions e HorizontalOptions questi
attriubuti attributi diventano property delle rispettive classi
e vengono detti Porperty Attributes
 Tutti questi hanno corrispondente tipo C# visto che
XAML 竪 fortemente tipizzato
Corrispondenza Code-Behind
 Ogni elemento e attributo nel file xml XAML ha sempre
una corrispondenza nel code-behind che possa essere
una classe C# o property.
 Durante la build viene creata la corrispondente classe
partial esegue il parsing del file XAML e crea gli oggetti in
esso contenuti
Corrispondenza Code-Behind (2)
namespace App1
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
}
}
Come facciamo...
 Come 竪 possibile armonizzare codice e markup?
 Come evitare markup ripetitivo?
 Creare XAML riutilizzabile?
Es. Rotation (1)
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App2RotText.MainPage">
<Grid>
<Label Text=" ROTATION"
FontSize="32"
Grid.Column="1"
VerticalOptions="Center"
HorizontalOptions="Start"
AnchorX="0"
Rotation="0"/>
.<!-- MOLTE RIPETIZIONI DELLO STESSO CODICE-->
<Label Text=" ROTATION"
FontSize="32"
Grid.Column="1"
VerticalOptions="Center"
HorizontalOptions="Start"
AnchorX="0"
Rotation="67.5"/>
</Grid>
</ContentPage>
Es. Rotation (2)
Es. Rotation (3)
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App2RotText.MainPage">
<Grid>
<Grid.Resources>
<Style x:Key="labelStyle" TargetType="Label">
<Setter Property="Text" Value=" ROTATION" />
<Setter Property="FontSize" Value="32" />
<Setter Property="Grid.Column" Value="1" />
<Setter Property="VerticalOptions" Value="Center" />
<Setter Property="HorizontalOptions" Value="Start" />
<Setter Property="AnchorX" Value="0" />
</Style>
</Grid.Resources>
<Label Style="{StaticResource labelStyle}" Rotation="0" />
<Label Style="{StaticResource labelStyle}" Rotation="22.5" />
<Label Style="{StaticResource labelStyle}" Rotation="45" />
<Label Style="{StaticResource labelStyle}" Rotation="67.5" />
<Label Style="{StaticResource labelStyle}" Rotation="90" />
<Label Style="{StaticResource labelStyle}" Rotation="102.5" />
<Label Style="{StaticResource labelStyle}" Rotation="125" />
</Grid>
</ContentPage>
Resource Dictionary
 Per risolvere la mancanza loop Xamarin possiede una feature chiamata Resource Dictionary
 Questo contiene elementi Style deve avere una chiave del del dizionario che contiene un
set di oggetti setter
 Ogni oggetto Setter assegna un valore a una Property
 Questi oggetti setter impostano caratteristica grafica, creando un stile riutilizzabile su pi湛
elementi xml
 E possibile semplificare eliminando la dichiarazione della chiave, lo style verr applicato se c竪
un matching con il target type. Questo viene detto Implicit Style
Implicit Style
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App2RotText.MainPage">
<Grid>
<Grid.Resources>
<Style TargetType="Label">
<Setter Property="Text" Value=" ROTATION" />
<Setter Property="FontSize" Value="32" />
<Setter Property="Grid.Column" Value="1" />
<Setter Property="VerticalOptions" Value="Center" />
<Setter Property="HorizontalOptions" Value="Start" />
<Setter Property="AnchorX" Value="0" />
</Style>
</Grid.Resources>
<Label Rotation="0" />
<Label Rotation="22.5" />
<Label Rotation="45" />
<Label Rotation="67.5" />
<Label Rotation="90" />
<Label Rotation="102.5" />
<Label Rotation="125" />
</Grid>
</ContentPage>
Armonia tra c# e xaml
 Qualcosa simile a un loop 竪 possibile eseguirlo tramite resource
dictionary
 Se volessimo eseguire una funzione particolare per ogni elemento
xaml, dovremmo usare il meccanismo della Markup Extension
 Per esempio se volessimo cambiare il colore della scritta secondo i
colori dellarcobaleno ci verrebbe utile scrivere una Markup
Exstension che imposti il colore tramite codifica HLS
Markup Extension (1)
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace App2RotText
{
public class HlsColorExtension : IMarkupExtension
{
public double H { get; set; }
public double L { get; set; }
public double S { get; set; }
public double A { get; set; }
public HlsColorExtension()
{
A = 1;
}
public object ProvideValue(IServiceProvider serviceProvider)
{
return Color.FromHsla(H, S, L, A);
}
}
}
Markup Extension (2)
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:App2RotText"
x:Class="App2RotText.MainPage">
<Grid>
<Grid.Resources>
<Style TargetType="Label">
<Setter Property="Text" Value=" ROTATION" />
<Setter Property="FontSize" Value="32" />
<Setter Property="Grid.Column" Value="1" />
<Setter Property="VerticalOptions" Value="Center" />
<Setter Property="HorizontalOptions" Value="Start" />
<Setter Property="AnchorX" Value="0" />
</Style>
</Grid.Resources>
<Label Rotation="0" TextColor="{local:HlsColor H=0.0000, S=1, L=0.5}"/>
<Label Rotation="22.5" TextColor="{local:HlsColor H=0.0635, S=1, L=0.5}" />
<Label Rotation="45" TextColor="{local:HlsColor H=0.1250, S=1, L=0.5}" />
<Label Rotation="67.5" TextColor="{local:HlsColor H=0.1875, S=1, L=0.5}" />
<Label Rotation="90" TextColor="{local:HlsColor H=0.2500, S=1, L=0.5}" />
<Label Rotation="102.5" TextColor="{local:HlsColor H=0.3125, S=1, L=0.5}" />
<Label Rotation="125" TextColor="{local:HlsColor H=0.3750, S=1, L=0.5}" />
</Grid>
</ContentPage>
Markup Extension (3)
Binding
 Binding anche noto come DataBinding connette due
property di due oggetti
 I cambiamenti di una property su unoggetto si riflettono
sullaltro oggetto, vicendevolmente
 Un oggetto risiede nei dati, mentre, laltro risiede nella UI
Es. No Data Binding (1)
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App3RotEvent.MainPage">
<StackLayout>
<Label
x:Name="rotationLabel"
Text="ROTATION"
FontSize="Large"
FontAttributes="Bold"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<際際滷r
Minimum="0"
Maximum="360"
ValueChanged="On際際滷rValueChanged"/>
<Label
x:Name="displayLabel"
Text="0"
FontSize="Medium"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
Es. No Data Binding (2)
 Questo esempio mostra un testo ruotato tramite slider e il
corrispondente grado di rotazione nel label sottostante
 On際際滷rValueChanged indica un event handler che deve
essere implementato nel code behind
 Il parser di XAML crea due campi privati con nome
rotationLabel e displayLabel ed in ogni parte del codice
potr嘆 accedervi
Es. No Data Binding (3)
using System;
using Xamarin.Forms;
namespace App3RotEvent
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private void On際際滷rValueChanged(object sender, ValueChangedEventArgs args)
{
rotationLabel.Rotation = (double)args.NewValue;
displayLabel.Text = String.Format("Rotation = {0:F2} degrtees", args.NewValue);
}
}
}
Es. Data Binding (1)
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App4RotEventBind.MainPage">
<StackLayout>
<Label
Text="ROTATION"
Rotation="{Binding Source={x:Reference slider},
Path=Value,
Mode=TwoWay}"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<際際滷r x:Name="slider"
Minimum="-360"
Maximum="360"
/>
<Label Text="{Binding Source={x:Reference slider},
Path=Value,
StringFormat='Rotation = {0:F2} degrees'}"
FontSize="Medium"
FontAttributes="Bold"/>
</StackLayout>
</ContentPage>
Es. Data Binding (2)
 <Label Rotation="{Binding Source={x:Reference slider},
 Path=Value,
 Mode=TwoWay} ...
 Questa Innested markup extension imposta il data
binding e associa la Property Rotation del label corrente
con la Property value delloggetto con Name slider
 TwoWay dice che il data binding in entrambe le direzioni
Es. Data Binding (3)
 <Label Text="{Binding Source={x:Reference slider},
 Path=Value,
 StringFormat='Rotation = {0:F2} degrees'}" .
 Imposta il data binding e associa la Property Text del label corrente con la
Property value delloggetto con Name slider
 StringFormat ci permette di formattare il testo assegnato alla property text
Es. Data Binding (4)
Es. Data Binding (5)
 Grazie al data binding abbiamo eliminato la parte di code
behind
 La parte di codice eliminata non sarebbe stata riutilizzabile
Esercizi - Data Binding
 Esercizio 1.A Aggiungere allesempio precedente un Entry
che chiamiamo entryDegree, che imposta il grado di
rotazione sia su slider che su label. Eseguire lo stesso in
modalit Binding e No Binding;
 Esercizio 1.B Partendo dal Esercizio 1.A aggiungere un
tasto resetButton che porta 0 i gradi gli altri Object
Elements
Es. Switch Color No Binding (1)
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App4SwitchColor.MainPage">
<StackLayout>
<Label x:Name="sampleLabel"
Text="Switch Color"
FontSize="Large"
FontAttributes="Bold"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Switch x:Name="switch"
HorizontalOptions="Center"
Toggled="OnSwitchedToggled"
/>
<Label
x:Name="displayLabel"
FontSize="Large"
FontAttributes="Bold"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
/>
</StackLayout>
</ContentPage>
Es. Switch Color No Binding (2)
using Xamarin.Forms;
namespace App4SwitchColor
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private void OnSwitchedToggled(object sender, ToggledEventArgs args)
{
sampleLabel.TextColor = args.Value ? Color.Red : Color.Blue;
displayLabel.Text = "The color is " + (args.Value ? "Red" : "Blue");
}
}
}
Es. Switch Color No Binding (3)
Es. Switch Color Binding (1)
 Ora sto sostituiremo questo event handler con il data
binding
 Ci troviamo di fronte un problema che la toggle property
dello switch 竪 di tipo bool, ma il databing richiede un tipo
Color
 Quello di cui abbiamo bisogno 竪 di un convertitore di tipo
chiamato Value Converter o Binding Converter
Es. Switch Color Binding (2)
using System;
using System.Globalization;
using Xamarin.Forms;
namespace App5SwitchColorBinding
{
public class BoolToColorConverter : IValueConverter
{
public Color TrueColor { get; set; }
public Color FalseColor { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool)value ? TrueColor : FalseColor;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return false;
}
}
}
Es. Switch Color Binding (3)
using System;
using System.Globalization;
using Xamarin.Forms;
namespace App5SwitchColorBinding
{
public class BoolToStringConverter : IValueConverter
{
public string TrueText { get; set; }
public string FalseText { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool)value ? TrueText : FalseText;
}
//not uesed
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return false;
}
}
}
Es. Switch Color Binding (4)
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:App5SwitchColorBinding"
x:Class="App5SwitchColorBinding.MainPage">
<ContentPage.Resources>
<ResourceDictionary>
<local:BoolToColorConverter x:Key="boolToColor" TrueColor="Blue" FalseColor="Red" />
<local:BoolToStringConverter x:Key="boolToString" TrueText="The color is Blue" FalseText="The color is Red" />
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<Label Text="Converter"
TextColor="{Binding Source={x:Reference switch},
Path=IsToggled,
Converter={StaticResource boolToColor}}"
FontSize="Large"
FontAttributes="Bold"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Switch x:Name="switch"
HorizontalOptions="Center" />
<Label Text="{Binding Source={x:Reference switch},
Path=IsToggled,
Converter={StaticResource boolToString}}"
FontSize="Large"
FontAttributes="Bold"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"/>
</StackLayout>
</ContentPage>
Es. Switch Color Binding (5)
 Abbiamo sostituito del codice con dellaltro codice,
ma il codice prodotto con il Data Binding 竪
riutilizzabile
 Il codice prodotti negli Event Handler non 竪
riutilizzabile
Trigger
 Tramite Trigger 竪 possibile realizzare esempi di
applicazioni simili, senza Binding Converter, quindi,
senza scrivere codice C#.
 Trigger sono un modo generalizzato per rispondere a
un evento, al cambiamento di una property in un file
XAML o eseguendo un determinato codice
Es. Switch Color Trigger (1)
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App6SwitchColorTrigger.MainPage">
<StackLayout>
<Label Text="Trigger" TextColor="Red" FontSize="Large" FontAttributes="Bold" HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<Label.Triggers>
<DataTrigger TargetType="Label"
Binding="{Binding Source={x:Reference switch}, Path=IsToggled}"
Value="True">
<Setter Property="TextColor" Value="Blue"/>
</DataTrigger>
</Label.Triggers>
</Label>
<Switch x:Name="switch" HorizontalOptions="Center" />
<Label Text="The color is Red" FontSize="Large" FontAttributes="Bold" HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<Label.Triggers>
<DataTrigger TargetType="Label"
Binding="{Binding Source={x:Reference switch}, Path=IsToggled}"
Value="True">
<Setter Property="Text" Value="The color is Blue" />
</DataTrigger>
</Label.Triggers>
</Label>
</StackLayout>
</ContentPage>
Es. Switch Color Trigger (2)
 Ogni elemento visuale ha un valore di default
 es. <Label Text="The color is Red"..
 Ogni elemento visuale possiede una collection property di tipo Triggers e ad essa possiamo aggiungere unazione DataTrigger associata
alla property du unaltro elemento
 es. <Label.Triggers>
 <DataTrigger TargetType="Label"
 Binding="{Binding Source={x:Reference switch}, Path=IsToggled}"
 Value="True">
 <Setter Property="Text" Value="The color is Blue" />
 </DataTrigger>
Utilit Trigger (1)
 I Trigger vengono utili inibire azioni quando non sono
permesse su determinati elementi della UI
 Ad es per disabilitare un pulsante salva file quando non 竪
presente il testo associato nella corrispondente text box
Utilit Trigger (2)
Utilit Trigger (3)
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:App7BtnDis"
x:Class="App7BtnDis.MainPage"
Padding="20, 50">
<StackLayout Spacing="20">
<Entry x:Name="entry"
Text=""
Keyboard="Url"
Placeholder="enter filename"/>
<Button Text="Save"
FontSize="Medium"
HorizontalOptions="Center">
<Button.Triggers>
<DataTrigger TargetType="Button"
Binding="{Binding Source={x:Reference entry},
Path=Text.Length}"
Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Button.Triggers>
</Button>
</StackLayout>
</ContentPage>
Multi Trigger Crendenziali
<Entry x:Name="user"
Text=""
Placeholder="user name" />
<Entry x:Name="password"
Text=""
Placeholder="user name"
IsPassword="true" />
<Button Text="Enter"
BackgroundColor="LightSeaGreen"
TextColor="White"
IsEnabled="false">
<Button.Triggers>
<MultiTrigger TargetType="Button">
<MultiTrigger.Conditions>
<BindingCondition Binding="{Binding Source={x:Reference user},
Path=Text}"
Value="Pippo" />
<BindingCondition Binding="{Binding Source={x:Reference password},
Path=Text}"
Value="1234" />
</MultiTrigger.Conditions>
<Setter Property="IsEnabled" Value="true" />
</MultiTrigger>
</Button.Triggers>
</Button>
Anatomia di un File XAML
 Ogni applicazione ha un file App.Xaml e un file App.Xaml.cs
detto C# code-behind
 App, il file XAML;
 App.Xaml.cs, un C# code-behind file associato al file XAML
 App.xaml 竪 il punto di partenza dichiarativo della tua
applicazione
 Entrambe App.xaml e App.xaml.cs contribuiscono a una classe
denominata App che deriva da Application
Classe App di Xamarin.Forms
 La classe App che deriva da Application offre le seguenti
funzionalit
 Una propriet MainPage, dove deve essere impostata la
pagina iniziale per l'app
 Un dizionario Properties persistente per archiviare valori
sullo stato del ciclo di vita
 Una propriet Current statica che contiene un riferimento
all'oggetto applicazione corrente.
Ciclo di vita (1)
 La classe Application contiene tre metodi virtuali che
possono essere sottoposti a override per gestire i metodi
del ciclo di vita
 OnStart Chiamato all'avvio dell'applicazione.
 OnSleep Chiamato ogni volta che l'applicazione passa in
background.
 OnResume Chiamato alla ripresa dell'applicazione, dopo il
passaggio in background.
Ciclo di vita (2)
 Non 竪 disponibile alcun metodo per la terminazione
dell'applicazione. In circostanze normali, ovvero non in
caso di arresto anomalo, la terminazione
dell'applicazione verr eseguita dallo stato OnSleep,
senza l'invio di notifiche aggiuntive al codice.
Ciclo di vita (3)
 Per rilevare quando questi metodi vengono chiamati, si va ad eseguire
un override di ciascun metodo partendo dalla classe Application
implementando una chiamata WriteLine in ognuno
protected override void OnStart()
{
Debug.WriteLine ("OnStart");
}
protected override void OnSleep()
{
Debug.WriteLine ("OnSleep");
}
protected override void OnResume()
{
Debug.WriteLine ("OnResume");
}

More Related Content

Xaml su Xamarin

  • 1. XAML Xamarin XAML (eXtensible Application Markup Language)
  • 2. XAML intro (1) XAML (eXtensible Application Markup Language) consente agli sviluppatori di definire le interfacce utente nelle applicazioni Xamarin.Forms tramite markup anzich辿 codice. XAML 竪 particolarmente adatto per l'uso con l'architettura delle applicazioni MVVM (Model-View-ViewModel) pi湛 diffusi: XAML definisce la vista collegata al ViewModel codice tramite le associazioni di dati basati su XAML.
  • 3. XAML intro (2) XAML 竪 un linguaggio basato su XML creato da Microsoft come alternativa al codice di programmazione per la creazione di istanze e inizializzazione di oggetti e per organizzare gli oggetti nelle gerarchie padre-figlio. XAML fa parte di xamarin.Forms, al suo interno, lo sviluppatore pu嘆 definire le interfacce utente: viste, layout e pagine
  • 4. C# e XAML (2) Code + Markup ---------------------- Awesome Apps
  • 5. C# e XAML (3) XAML 竪 un file xml Ogni elemento 竪 organizzato secondo una gerarchia padre figlio Ogni elemento pu嘆 avere degli attributi
  • 6. C# e XAML (1) C# 竪 un linguaggio Procedurale XAML 竪 un linguaggio dichiarativo C# definisce linterazione tra Oggetti UI XAML definisce gli oggetti che compongono UI
  • 7. Esempio di XAML 1) <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 2) xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 3) x:Class="App1.MainPage"> 4) <StackLayout> 5) <!-- Place new controls here --> 6) <Label Text="Welcome to Xamarin.Forms!" 7) HorizontalOptions="Center" 8) VerticalOptions="CenterAndExpand" /> 9) <Button Text="Click ME!" HorizontalOptions="Center" /> 10) <際際滷r VerticalOptions="CenterAndExpand" /> 11) </StackLayout> 12) </ContentPage>
  • 9. XAML Namespaces (1) <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="App1.MainPage"> <StackLayout> <Label Text="Welcome to Xamarin.Forms!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> <Button Text="Click ME!" HorizontalOptions="Center" /> <際際滷r VerticalOptions="CenterAndExpand" /> </StackLayout> </ContentPage>
  • 10. XAML Namespaces (2) xmlns="http://xamarin.com/schemas/2014/forms" include le definizioni di xamarin.forms e definisce tutti gli elementi senza prefisso (x) (es. ContentPage) xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" include tutti i prefissi prefissi usati dichiarare spazi dei nomi non predefiniti . Come x:Class che specifica il nome della classe associata allo XAML nel code- behind. Nel nostro caso App1.MainPage.
  • 11. Classi ed elementi (1) <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="App1.MainPage"> <StackLayout> <Label Text="Welcome to Xamarin.Forms!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> <Button Text="Click ME!" HorizontalOptions="Center" /> <際際滷r VerticalOptions="CenterAndExpand" /> </StackLayout> </ContentPage>
  • 12. Classi ed elementi (2) ContentPage, StackLayout, Label, Button e 際際滷r sono elementi xml che diventano classi C# nel code-behind e vengono chiamati Object Elements
  • 13. Attributi (1) <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="App1.MainPage"> <StackLayout> <Label Text="Welcome to Xamarin.Forms!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> <Button Text="Click ME!" HorizontalOptions="Center" /> <際際滷r VerticalOptions="CenterAndExpand" /> </StackLayout> </ContentPage>
  • 14. Attributi (2) Text, FontSize, VerticalOptions e HorizontalOptions questi attriubuti attributi diventano property delle rispettive classi e vengono detti Porperty Attributes Tutti questi hanno corrispondente tipo C# visto che XAML 竪 fortemente tipizzato
  • 15. Corrispondenza Code-Behind Ogni elemento e attributo nel file xml XAML ha sempre una corrispondenza nel code-behind che possa essere una classe C# o property. Durante la build viene creata la corrispondente classe partial esegue il parsing del file XAML e crea gli oggetti in esso contenuti
  • 16. Corrispondenza Code-Behind (2) namespace App1 { public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); } } }
  • 17. Come facciamo... Come 竪 possibile armonizzare codice e markup? Come evitare markup ripetitivo? Creare XAML riutilizzabile?
  • 18. Es. Rotation (1) <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="App2RotText.MainPage"> <Grid> <Label Text=" ROTATION" FontSize="32" Grid.Column="1" VerticalOptions="Center" HorizontalOptions="Start" AnchorX="0" Rotation="0"/> .<!-- MOLTE RIPETIZIONI DELLO STESSO CODICE--> <Label Text=" ROTATION" FontSize="32" Grid.Column="1" VerticalOptions="Center" HorizontalOptions="Start" AnchorX="0" Rotation="67.5"/> </Grid> </ContentPage>
  • 20. Es. Rotation (3) <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="App2RotText.MainPage"> <Grid> <Grid.Resources> <Style x:Key="labelStyle" TargetType="Label"> <Setter Property="Text" Value=" ROTATION" /> <Setter Property="FontSize" Value="32" /> <Setter Property="Grid.Column" Value="1" /> <Setter Property="VerticalOptions" Value="Center" /> <Setter Property="HorizontalOptions" Value="Start" /> <Setter Property="AnchorX" Value="0" /> </Style> </Grid.Resources> <Label Style="{StaticResource labelStyle}" Rotation="0" /> <Label Style="{StaticResource labelStyle}" Rotation="22.5" /> <Label Style="{StaticResource labelStyle}" Rotation="45" /> <Label Style="{StaticResource labelStyle}" Rotation="67.5" /> <Label Style="{StaticResource labelStyle}" Rotation="90" /> <Label Style="{StaticResource labelStyle}" Rotation="102.5" /> <Label Style="{StaticResource labelStyle}" Rotation="125" /> </Grid> </ContentPage>
  • 21. Resource Dictionary Per risolvere la mancanza loop Xamarin possiede una feature chiamata Resource Dictionary Questo contiene elementi Style deve avere una chiave del del dizionario che contiene un set di oggetti setter Ogni oggetto Setter assegna un valore a una Property Questi oggetti setter impostano caratteristica grafica, creando un stile riutilizzabile su pi湛 elementi xml E possibile semplificare eliminando la dichiarazione della chiave, lo style verr applicato se c竪 un matching con il target type. Questo viene detto Implicit Style
  • 22. Implicit Style <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="App2RotText.MainPage"> <Grid> <Grid.Resources> <Style TargetType="Label"> <Setter Property="Text" Value=" ROTATION" /> <Setter Property="FontSize" Value="32" /> <Setter Property="Grid.Column" Value="1" /> <Setter Property="VerticalOptions" Value="Center" /> <Setter Property="HorizontalOptions" Value="Start" /> <Setter Property="AnchorX" Value="0" /> </Style> </Grid.Resources> <Label Rotation="0" /> <Label Rotation="22.5" /> <Label Rotation="45" /> <Label Rotation="67.5" /> <Label Rotation="90" /> <Label Rotation="102.5" /> <Label Rotation="125" /> </Grid> </ContentPage>
  • 23. Armonia tra c# e xaml Qualcosa simile a un loop 竪 possibile eseguirlo tramite resource dictionary Se volessimo eseguire una funzione particolare per ogni elemento xaml, dovremmo usare il meccanismo della Markup Extension Per esempio se volessimo cambiare il colore della scritta secondo i colori dellarcobaleno ci verrebbe utile scrivere una Markup Exstension che imposti il colore tramite codifica HLS
  • 24. Markup Extension (1) using System; using Xamarin.Forms; using Xamarin.Forms.Xaml; namespace App2RotText { public class HlsColorExtension : IMarkupExtension { public double H { get; set; } public double L { get; set; } public double S { get; set; } public double A { get; set; } public HlsColorExtension() { A = 1; } public object ProvideValue(IServiceProvider serviceProvider) { return Color.FromHsla(H, S, L, A); } } }
  • 25. Markup Extension (2) <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:App2RotText" x:Class="App2RotText.MainPage"> <Grid> <Grid.Resources> <Style TargetType="Label"> <Setter Property="Text" Value=" ROTATION" /> <Setter Property="FontSize" Value="32" /> <Setter Property="Grid.Column" Value="1" /> <Setter Property="VerticalOptions" Value="Center" /> <Setter Property="HorizontalOptions" Value="Start" /> <Setter Property="AnchorX" Value="0" /> </Style> </Grid.Resources> <Label Rotation="0" TextColor="{local:HlsColor H=0.0000, S=1, L=0.5}"/> <Label Rotation="22.5" TextColor="{local:HlsColor H=0.0635, S=1, L=0.5}" /> <Label Rotation="45" TextColor="{local:HlsColor H=0.1250, S=1, L=0.5}" /> <Label Rotation="67.5" TextColor="{local:HlsColor H=0.1875, S=1, L=0.5}" /> <Label Rotation="90" TextColor="{local:HlsColor H=0.2500, S=1, L=0.5}" /> <Label Rotation="102.5" TextColor="{local:HlsColor H=0.3125, S=1, L=0.5}" /> <Label Rotation="125" TextColor="{local:HlsColor H=0.3750, S=1, L=0.5}" /> </Grid> </ContentPage>
  • 27. Binding Binding anche noto come DataBinding connette due property di due oggetti I cambiamenti di una property su unoggetto si riflettono sullaltro oggetto, vicendevolmente Un oggetto risiede nei dati, mentre, laltro risiede nella UI
  • 28. Es. No Data Binding (1) <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="App3RotEvent.MainPage"> <StackLayout> <Label x:Name="rotationLabel" Text="ROTATION" FontSize="Large" FontAttributes="Bold" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> <際際滷r Minimum="0" Maximum="360" ValueChanged="On際際滷rValueChanged"/> <Label x:Name="displayLabel" Text="0" FontSize="Medium" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> </StackLayout> </ContentPage>
  • 29. Es. No Data Binding (2) Questo esempio mostra un testo ruotato tramite slider e il corrispondente grado di rotazione nel label sottostante On際際滷rValueChanged indica un event handler che deve essere implementato nel code behind Il parser di XAML crea due campi privati con nome rotationLabel e displayLabel ed in ogni parte del codice potr嘆 accedervi
  • 30. Es. No Data Binding (3) using System; using Xamarin.Forms; namespace App3RotEvent { public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); } private void On際際滷rValueChanged(object sender, ValueChangedEventArgs args) { rotationLabel.Rotation = (double)args.NewValue; displayLabel.Text = String.Format("Rotation = {0:F2} degrtees", args.NewValue); } } }
  • 31. Es. Data Binding (1) <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="App4RotEventBind.MainPage"> <StackLayout> <Label Text="ROTATION" Rotation="{Binding Source={x:Reference slider}, Path=Value, Mode=TwoWay}" FontSize="Large" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> <際際滷r x:Name="slider" Minimum="-360" Maximum="360" /> <Label Text="{Binding Source={x:Reference slider}, Path=Value, StringFormat='Rotation = {0:F2} degrees'}" FontSize="Medium" FontAttributes="Bold"/> </StackLayout> </ContentPage>
  • 32. Es. Data Binding (2) <Label Rotation="{Binding Source={x:Reference slider}, Path=Value, Mode=TwoWay} ... Questa Innested markup extension imposta il data binding e associa la Property Rotation del label corrente con la Property value delloggetto con Name slider TwoWay dice che il data binding in entrambe le direzioni
  • 33. Es. Data Binding (3) <Label Text="{Binding Source={x:Reference slider}, Path=Value, StringFormat='Rotation = {0:F2} degrees'}" . Imposta il data binding e associa la Property Text del label corrente con la Property value delloggetto con Name slider StringFormat ci permette di formattare il testo assegnato alla property text
  • 35. Es. Data Binding (5) Grazie al data binding abbiamo eliminato la parte di code behind La parte di codice eliminata non sarebbe stata riutilizzabile
  • 36. Esercizi - Data Binding Esercizio 1.A Aggiungere allesempio precedente un Entry che chiamiamo entryDegree, che imposta il grado di rotazione sia su slider che su label. Eseguire lo stesso in modalit Binding e No Binding; Esercizio 1.B Partendo dal Esercizio 1.A aggiungere un tasto resetButton che porta 0 i gradi gli altri Object Elements
  • 37. Es. Switch Color No Binding (1) <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="App4SwitchColor.MainPage"> <StackLayout> <Label x:Name="sampleLabel" Text="Switch Color" FontSize="Large" FontAttributes="Bold" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> <Switch x:Name="switch" HorizontalOptions="Center" Toggled="OnSwitchedToggled" /> <Label x:Name="displayLabel" FontSize="Large" FontAttributes="Bold" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> </StackLayout> </ContentPage>
  • 38. Es. Switch Color No Binding (2) using Xamarin.Forms; namespace App4SwitchColor { public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); } private void OnSwitchedToggled(object sender, ToggledEventArgs args) { sampleLabel.TextColor = args.Value ? Color.Red : Color.Blue; displayLabel.Text = "The color is " + (args.Value ? "Red" : "Blue"); } } }
  • 39. Es. Switch Color No Binding (3)
  • 40. Es. Switch Color Binding (1) Ora sto sostituiremo questo event handler con il data binding Ci troviamo di fronte un problema che la toggle property dello switch 竪 di tipo bool, ma il databing richiede un tipo Color Quello di cui abbiamo bisogno 竪 di un convertitore di tipo chiamato Value Converter o Binding Converter
  • 41. Es. Switch Color Binding (2) using System; using System.Globalization; using Xamarin.Forms; namespace App5SwitchColorBinding { public class BoolToColorConverter : IValueConverter { public Color TrueColor { get; set; } public Color FalseColor { get; set; } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return (bool)value ? TrueColor : FalseColor; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return false; } } }
  • 42. Es. Switch Color Binding (3) using System; using System.Globalization; using Xamarin.Forms; namespace App5SwitchColorBinding { public class BoolToStringConverter : IValueConverter { public string TrueText { get; set; } public string FalseText { get; set; } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return (bool)value ? TrueText : FalseText; } //not uesed public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return false; } } }
  • 43. Es. Switch Color Binding (4) <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:App5SwitchColorBinding" x:Class="App5SwitchColorBinding.MainPage"> <ContentPage.Resources> <ResourceDictionary> <local:BoolToColorConverter x:Key="boolToColor" TrueColor="Blue" FalseColor="Red" /> <local:BoolToStringConverter x:Key="boolToString" TrueText="The color is Blue" FalseText="The color is Red" /> </ResourceDictionary> </ContentPage.Resources> <StackLayout> <Label Text="Converter" TextColor="{Binding Source={x:Reference switch}, Path=IsToggled, Converter={StaticResource boolToColor}}" FontSize="Large" FontAttributes="Bold" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> <Switch x:Name="switch" HorizontalOptions="Center" /> <Label Text="{Binding Source={x:Reference switch}, Path=IsToggled, Converter={StaticResource boolToString}}" FontSize="Large" FontAttributes="Bold" HorizontalOptions="Center" VerticalOptions="CenterAndExpand"/> </StackLayout> </ContentPage>
  • 44. Es. Switch Color Binding (5) Abbiamo sostituito del codice con dellaltro codice, ma il codice prodotto con il Data Binding 竪 riutilizzabile Il codice prodotti negli Event Handler non 竪 riutilizzabile
  • 45. Trigger Tramite Trigger 竪 possibile realizzare esempi di applicazioni simili, senza Binding Converter, quindi, senza scrivere codice C#. Trigger sono un modo generalizzato per rispondere a un evento, al cambiamento di una property in un file XAML o eseguendo un determinato codice
  • 46. Es. Switch Color Trigger (1) <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="App6SwitchColorTrigger.MainPage"> <StackLayout> <Label Text="Trigger" TextColor="Red" FontSize="Large" FontAttributes="Bold" HorizontalOptions="Center" VerticalOptions="CenterAndExpand"> <Label.Triggers> <DataTrigger TargetType="Label" Binding="{Binding Source={x:Reference switch}, Path=IsToggled}" Value="True"> <Setter Property="TextColor" Value="Blue"/> </DataTrigger> </Label.Triggers> </Label> <Switch x:Name="switch" HorizontalOptions="Center" /> <Label Text="The color is Red" FontSize="Large" FontAttributes="Bold" HorizontalOptions="Center" VerticalOptions="CenterAndExpand"> <Label.Triggers> <DataTrigger TargetType="Label" Binding="{Binding Source={x:Reference switch}, Path=IsToggled}" Value="True"> <Setter Property="Text" Value="The color is Blue" /> </DataTrigger> </Label.Triggers> </Label> </StackLayout> </ContentPage>
  • 47. Es. Switch Color Trigger (2) Ogni elemento visuale ha un valore di default es. <Label Text="The color is Red".. Ogni elemento visuale possiede una collection property di tipo Triggers e ad essa possiamo aggiungere unazione DataTrigger associata alla property du unaltro elemento es. <Label.Triggers> <DataTrigger TargetType="Label" Binding="{Binding Source={x:Reference switch}, Path=IsToggled}" Value="True"> <Setter Property="Text" Value="The color is Blue" /> </DataTrigger>
  • 48. Utilit Trigger (1) I Trigger vengono utili inibire azioni quando non sono permesse su determinati elementi della UI Ad es per disabilitare un pulsante salva file quando non 竪 presente il testo associato nella corrispondente text box
  • 50. Utilit Trigger (3) <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:App7BtnDis" x:Class="App7BtnDis.MainPage" Padding="20, 50"> <StackLayout Spacing="20"> <Entry x:Name="entry" Text="" Keyboard="Url" Placeholder="enter filename"/> <Button Text="Save" FontSize="Medium" HorizontalOptions="Center"> <Button.Triggers> <DataTrigger TargetType="Button" Binding="{Binding Source={x:Reference entry}, Path=Text.Length}" Value="0"> <Setter Property="IsEnabled" Value="False" /> </DataTrigger> </Button.Triggers> </Button> </StackLayout> </ContentPage>
  • 51. Multi Trigger Crendenziali <Entry x:Name="user" Text="" Placeholder="user name" /> <Entry x:Name="password" Text="" Placeholder="user name" IsPassword="true" /> <Button Text="Enter" BackgroundColor="LightSeaGreen" TextColor="White" IsEnabled="false"> <Button.Triggers> <MultiTrigger TargetType="Button"> <MultiTrigger.Conditions> <BindingCondition Binding="{Binding Source={x:Reference user}, Path=Text}" Value="Pippo" /> <BindingCondition Binding="{Binding Source={x:Reference password}, Path=Text}" Value="1234" /> </MultiTrigger.Conditions> <Setter Property="IsEnabled" Value="true" /> </MultiTrigger> </Button.Triggers> </Button>
  • 52. Anatomia di un File XAML Ogni applicazione ha un file App.Xaml e un file App.Xaml.cs detto C# code-behind App, il file XAML; App.Xaml.cs, un C# code-behind file associato al file XAML App.xaml 竪 il punto di partenza dichiarativo della tua applicazione Entrambe App.xaml e App.xaml.cs contribuiscono a una classe denominata App che deriva da Application
  • 53. Classe App di Xamarin.Forms La classe App che deriva da Application offre le seguenti funzionalit Una propriet MainPage, dove deve essere impostata la pagina iniziale per l'app Un dizionario Properties persistente per archiviare valori sullo stato del ciclo di vita Una propriet Current statica che contiene un riferimento all'oggetto applicazione corrente.
  • 54. Ciclo di vita (1) La classe Application contiene tre metodi virtuali che possono essere sottoposti a override per gestire i metodi del ciclo di vita OnStart Chiamato all'avvio dell'applicazione. OnSleep Chiamato ogni volta che l'applicazione passa in background. OnResume Chiamato alla ripresa dell'applicazione, dopo il passaggio in background.
  • 55. Ciclo di vita (2) Non 竪 disponibile alcun metodo per la terminazione dell'applicazione. In circostanze normali, ovvero non in caso di arresto anomalo, la terminazione dell'applicazione verr eseguita dallo stato OnSleep, senza l'invio di notifiche aggiuntive al codice.
  • 56. Ciclo di vita (3) Per rilevare quando questi metodi vengono chiamati, si va ad eseguire un override di ciascun metodo partendo dalla classe Application implementando una chiamata WriteLine in ognuno protected override void OnStart() { Debug.WriteLine ("OnStart"); } protected override void OnSleep() { Debug.WriteLine ("OnSleep"); } protected override void OnResume() { Debug.WriteLine ("OnResume"); }