Upload
others
View
4
Download
0
Embed Size (px)
Citation preview
Xamarin.Forms
Radosław Osiński
Xamarin.Forms first app
3 projects
.Net Standard → Shared code
iOS → platform specyfic code
Android → platform specyfic project
App.xaml.cspublic partial class App : Application
{public App(){
InitializeComponent();
MainPage = new MainPage();}protected override void OnStart(){
// Handle when your app starts}protected override void OnSleep(){
// Handle when your app sleeps}protected override void OnResume(){
// Handle when your app resumes}
}
Three virtual methods that can be overridden
to handle lifecycle methods:
OnStart - Called when the application starts.
OnSleep - Called each time the application
goes to the background.
OnResume - Called when the application is
resumed, after being sent to the background.
MainPage.xaml
<StackLayout><!-- Place new controls here --><Label Text="Welcome to Xamarin.Forms!"
HorizontalOptions="Center"VerticalOptions="CenterAndExpand" />
</StackLayout>
Page content
https://docs.microsoft.com/en-us/xamarin/get-started/first-app/?pivots=windows
Button
<StackLayout><!-- Place new controls here --><Label Text="Welcome to Xamarin.Forms!"
HorizontalOptions="Center"VerticalOptions="CenterAndExpand" />
<Button Text="Click me!" Clicked="Button_Clicked" /></StackLayout>
int count = 0;private void Button_Clicked(object sender, EventArgs e){
count++;((Button)sender).Text = $"You clicked {count} times";
}
Simple form
<StackLayout Margin="10,35,10,10"><Label Text="Notes"
HorizontalOptions="Center"FontAttributes="Bold" />
<Editor x:Name="_editor"Placeholder="Enter your note"HeightRequest="100" />
<Grid><Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /><ColumnDefinition Width="*" />
</Grid.ColumnDefinitions><Button Text="Save"
Clicked="OnSaveButtonClicked" /><Button Grid.Column="1"
Text="Delete"Clicked="OnDeleteButtonClicked"/>
</Grid></StackLayout>
https://docs.microsoft.com/en-us/xamarin/get-started/quickstarts/single-page?pivots=windows
<Editor x:Name="_editor"
• _editor visible on code behind
• Receive info from controlString text = _editor.Text;
• Send info to control_editor.Text = File.ReadAllText(_fileName);
Interacting with local filestring _fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "notes.txt");
public MainPage(){
InitializeComponent();if (File.Exists(_fileName)){
_editor.Text = File.ReadAllText(_fileName);}
}void OnSaveButtonClicked(object sender, EventArgs e){
File.WriteAllText(_fileName, _editor.Text);}void OnDeleteButtonClicked(object sender, EventArgs e){
if (File.Exists(_fileName)){
File.Delete(_fileName);}_editor.Text = string.Empty;
}
Multipage
From where navigation came from?
App.xaml.cs
public App(){
InitializeComponent();MainPage = new NavigationPage(new NotesPage());
}
Without navigation
public App(){
InitializeComponent();MainPage = new NotesPage();
}
Multipage
1. Create folder2. Create model
namespace Notes.Models{
public class Note{
public string Filename { get; set; }public string Text { get; set; }public DateTime Date { get; set; }
}}
Multipage
New page for adding notes
<StackLayout Margin="20"><Editor Placeholder="Enter your note"
Text="{Binding Text}"HeightRequest="100" />
<Grid><Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /><ColumnDefinition Width="*" />
</Grid.ColumnDefinitions><Button Text="Save"
Clicked="OnSaveButtonClicked" /><Button Grid.Column="1"
Text="Delete"Clicked="OnDeleteButtonClicked"/>
</Grid></StackLayout>
Multipage – note entry code behindasync void OnSaveButtonClicked(object sender, EventArgs e)
{var note = (Note)BindingContext;
if (string.IsNullOrWhiteSpace(note.Filename)){ // Save
var filename = Path.Combine(App.FolderPath, $"{Path.GetRandomFileName()}.notes.txt");File.WriteAllText(filename, note.Text);
}else{ // Update
File.WriteAllText(note.Filename, note.Text);}await Navigation.PopAsync();
}
async void OnDeleteButtonClicked(object sender, EventArgs e){
var note = (Note)BindingContext;if (File.Exists(note.Filename)){
File.Delete(note.Filename);}
await Navigation.PopAsync();}
Asynchronously removes the top
page from the navigation stack.
Multipage – creating NotesPage
<ContentPage.ToolbarItems><ToolbarItem Text="+"
Clicked="OnNoteAddedClicked" /></ContentPage.ToolbarItems>
<ListView x:Name="listView"Margin="20"ItemSelected="OnListViewItemSelected">
<ListView.ItemTemplate><DataTemplate>
<TextCell Text="{Binding Text}"Detail="{Binding Date}" />
</DataTemplate></ListView.ItemTemplate>
</ListView>
Multipage – set NotesPage as default
public App(){
InitializeComponent();
MainPage = new NavigationPage(new NotesPage());}
Constructor in App.xaml.cs:
Multipage – NotesPage code behind
protected override void OnAppearing(){
base.OnAppearing();
var notes = new List<Note>();
var files = Directory.EnumerateFiles(App.FolderPath, "*.notes.txt");foreach (var filename in files){
notes.Add(new Note{
Filename = filename,Text = File.ReadAllText(filename),Date = File.GetCreationTime(filename)
});}
listView.ItemsSource = notes.OrderBy(d => d.Date).ToList();
}
Run before page loading
Two events on the Application class that providenotification of pages appearing and disappearing:
PageAppearing - raised when a page is aboutto appear on the screen.
PageDisappearing - raised when a page is about to disappear from the screen.
Multipage - NotesPage code behind
<ContentPage.ToolbarItems><ToolbarItem Text="+" Clicked="OnNoteAddedClicked" />
</ContentPage.ToolbarItems>
async void OnNoteAddedClicked(object sender, EventArgs e){
await Navigation.PushAsync(new NoteEntryPage{
BindingContext = new Note()});
}
Multipage - NotesPage code behind<ListView x:Name="listView"
Margin="20"ItemSelected="OnListViewItemSelected">
<ListView.ItemTemplate><DataTemplate>
<TextCell Text="{Binding Text}" Detail="{Binding Date}" /></DataTemplate>
</ListView.ItemTemplate></ListView>
async void OnListViewItemSelected(object sender, SelectedItemChangedEventArgs e){
if (e.SelectedItem != null){
await Navigation.PushAsync(new NoteEntryPage{
BindingContext = e.SelectedItem as Note});
}}
App lifecycle
Lifecycle Methods
OnStart
OnSleep
OnResume
Page navigation events
PageApearing
PageDisapearing
ModalNavigationEvents
ModalPushing
ModalPushed
ModalPopping
ModalPopped
Navigation typesModal Navigation
• Full screen view leads to another full screen view
• View in background is inaccessible
• User need to interact with a view until it is removed
• To complete some task before continuing
• Examples
• Creating new email
• Adding item to list
Hierarchical Navigation
• User is led through a view series with ability to go back to previous screen
• Access to data previously inserted
• Examples
• Few step registration process
• Jumping between application pages Navigation.PushAsync();
Navigation.PushModalAsync();
Hierarchical NavigationUser is able to navigate through pages, forwards and backwards, as desired.
Modal Navigation Events
ModalPopped Event that is raised after a view has been popped modally.
ModalPopping Event that is raised when a view is modally popped.
ModalPushed Event that is raised after a view has been pushed modally.
ModalPushing Event that is raised when a view is modally pushed.
A modal page can be any of the Page types supported by Xamarin.Forms. To display a modal page the application willpush it onto the modal stack, where it will become the active page, as shown in the following diagram:
To return to the previous page the application will pop the current page from the modal stack, and the new topmost pagebecomes the active page, as shown in the following diagram:
Which navigation type should I use?
Design user flow First!
Questions you should ask:
What user should see?
What data user should provide?
What would be the next step?
Local SQLite.NET Database
https://docs.microsoft.com/en-us/xamarin/get-started/quickstarts/database?pivots=windows
Adopting model
using System;using SQLite;
namespace Notes.Models{
public class Note{
[PrimaryKey, AutoIncrement]public int ID { get; set; }public string Text { get; set; }public DateTime Date { get; set; }
}}
using System.Collections.Generic;using System.Threading.Tasks;using SQLite;using Notes.Models;
namespace Notes.Data{
public class NoteDatabase{
readonly SQLiteAsyncConnection _database;
public NoteDatabase(string dbPath){
_database = new SQLiteAsyncConnection(dbPath);_database.CreateTableAsync<Note>().Wait();
}
public Task<List<Note>> GetNotesAsync(){
return_database.Table<Note>().ToListAsync();
}
public Task<Note> GetNoteAsync(int id){
return _database.Table<Note>().Where(i => i.ID == id).FirstOrDefaultAsync();
}public Task<int> SaveNoteAsync(Note note)
{if (note.ID != 0){
return _database.UpdateAsync(note);}else{
return _database.InsertAsync(note);}
}
public Task<int> DeleteNoteAsync(Note note){
return _database.DeleteAsync(note);}
}}
Create the database.
Read data from it.
Write data to it. Delete data from it.
Update App.xaml.cs
static NoteDatabase database;
public static NoteDatabase Database{
get{
if (database == null){
database = newNoteDatabase(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Notes.db3"));
}return database;
}}
Read data when application loads
NotesPage.xaml.cs
protected override async void OnAppearing(){
base.OnAppearing();
listView.ItemsSource = await App.Database.GetNotesAsync();}
Save
Delete
async void OnSaveButtonClicked(object sender, EventArgs e){
var note = (Note)BindingContext;note.Date = DateTime.UtcNow;await App.Database.SaveNoteAsync(note);await Navigation.PopAsync();
}
async void OnDeleteButtonClicked(object sender, EventArgs e){
var note = (Note)BindingContext;await App.Database.DeleteNoteAsync(note);await Navigation.PopAsync();
}
Styling
• Colours
• Fonts
• Controls
https://docs.microsoft.com/en-us/xamarin/get-started/quickstarts/styling?pivots=windows
Styling Application Level – App.xaml<Application.Resources>
<Thickness x:Key="PageMargin">20</Thickness>
<!-- Colors --><Color x:Key="AppBackgroundColor">WhiteSmoke</Color><Color x:Key="iOSNavigationBarColor">WhiteSmoke</Color><Color x:Key="AndroidNavigationBarColor">#2196F3</Color><Color x:Key="iOSNavigationBarTextColor">Black</Color><Color x:Key="AndroidNavigationBarTextColor">White</Color>
<!-- Implicit styles --><Style TargetType="{x:Type NavigationPage}">
<Setter Property="BarBackgroundColor"Value="{OnPlatform iOS={StaticResource iOSNavigationBarColor},
Android={StaticResource AndroidNavigationBarColor}}" /><Setter Property="BarTextColor"
Value="{OnPlatform iOS={StaticResource iOSNavigationBarTextColor},Android={StaticResource AndroidNavigationBarTextColor}}" />
</Style>
<Style TargetType="{x:Type ContentPage}"ApplyToDerivedTypes="True">
<Setter Property="BackgroundColor"Value="{StaticResource AppBackgroundColor}" />
</Style></Application.Resources>
Thickness around the edges
Represents a color and
exposes it as RGBA and HSL values
Impact NavigationPage
Impact all ContentPages
Styles available in the application-level ResourceDictionary can be consumed throughout the application
Styling Page Level – ListView
<ContentPage.Resources><!-- Implicit styles --><Style TargetType="{x:Type ListView}">
<Setter Property="BackgroundColor"Value="{StaticResource AppBackgroundColor}" />
</Style></ContentPage.Resources>
Impact ListView background
+
ListView.Margin defined in application-Level
<Thickness x:Key="PageMargin">20</Thickness>
Styling Page Level – Modal Page
<ContentPage.Resources><!-- Implicit styles --><Style TargetType="{x:Type Editor}">
<Setter Property="BackgroundColor"Value="{StaticResource AppBackgroundColor}" />
</Style>
<Style TargetType="Button"ApplyToDerivedTypes="True"CanCascade="True">
<Setter Property="FontSize" Value="Medium" /><Setter Property="BackgroundColor" Value="LightGray" /><Setter Property="TextColor" Value="Black" /><Setter Property="BorderRadius" Value="5" />
</Style></ContentPage.Resources>
This code adds implicit styles for the Editor and Button views to the page-level ResourceDictionary, and sets the StackLayout.Margin property to a value defined in the application-level ResourceDictionary.
App Center
• Automate the lifecycle of your iOS, Android, Windows and macOS apps
• Connect your git repo (Azure DevOps, GitHub, Bitbucket)
• Test on thousands of real devices
• Distribute beta testers and app stores
• Monitor real-world usage with crash and analytics data
https://docs.microsoft.com/en-us/appcenter/
App Center
• CI – Continuous Integration• Managing development quality
• CQ – Continuous Quality• Support for multiple real devices
• CD – Continuous Delivery• Managing deployments
• CM – Continuous Monitoring• Monitoring traffic and use behaviour
• CE – Continuous Engagement• Push notification
https://docs.microsoft.com/en-us/appcenter/
Xamarin UI Tests – Testing on real devices
Memory and CPU usage
Ho long test took
Logs after test
https://channel9.msdn.com/Shows/XamarinShow/User-Interface-Automation-with-App-Center-Test?term=Xamarin%20UI%20test&lang-en=true
Xamarin UI Tests – Testing on real devices
https://channel9.msdn.com/Shows/XamarinShow/User-Interface-Automation-with-App-Center-Test?term=Xamarin%20UI%20test&lang-en=true
Screens from each device
Different android versions
Different device models
Select the tier for check the most popular devices
AppCenter - Supported test frameworks
• Appium
• Calabash
• Espresso
• Xamarin.UITests
Monitoring with AppCenter• Nuget packages
Microsoft.AppCenter.Analytics
Microsoft.AppCenter.Crashespackages
• App.xaml.cs
• On Start:
Tracking custom events: Analytics.TrackEvent("My custom event");
protected override void OnStart(){
// Handle when your app startsAppCenter.Start("android=64996e3f-eed7-40db-a47b-a0cbd25f222d;" +
"uwp={Your UWP App secret here};" +"ios={Your iOS App secret here}",typeof(Analytics), typeof(Crashes));
}
using Microsoft.AppCenter;using Microsoft.AppCenter.Analytics;using Microsoft.AppCenter.Crashes;
Push notifications with AppCenter
• NugetMicrosoft.AppCenter.Push
protected override void OnStart(){
// Handle when your app startsAppCenter.Start("android=64996e3f-eed7-40db-a47b-a0cbd25f222d;" +
"uwp={Your UWP App secret here};" +"ios={Your iOS App secret here}",typeof(Analytics), typeof(Crashes), typeof(Push));
}
Push notifications with AppCenter +
Set up Firebase Cloud Messaging• Create a project on the Firebase console.
• Then, press on the Android logo to create an application matching your package name. (Package name from AndrofidManifest.xml
• Go to the settings of the application.
• Download the google-services.json file.
• Copy this file to your Android project.
https://console.firebase.google.com/
https://channel9.msdn.com/Shows/XamarinShow/Push-Notifications-Made-Easy-with-App-Center?term=app%20center&lang-en=true
Integrate Firebase in application
• Close and reopen your solution.
• Open context menu on google-services.json file.
• Select GoogleServicesJson in Build Action. (VS: → GoogleServicesJson→ Properties → Build Action dropdown → GoogleServicesJson)
• Edit AndroidManifest.xml and insert the following elements inside the <application> section:
Finally last step:
Result:
Full architecture example
https://azure.microsoft.com/en-us/solutions/architecture/social-mobile-and-web-app-with-authentication/
Application Monitoring
Platform Monitoring Application Monitoring OMS Solutions Security Center
SmartHotel360 is a fictitious smart hospitality company showcasing the future of connected travel.
We built intelligent and personalized apps for guests, business travelers, and hotel managers. All powered
by the cloud, our best-in-class tools, our data platform, and Artificial Intelligence.
People. Process. Products.
What is DevOps?
DevOps is the union of people, process, and products to enable continuous delivery of value to your end users.
“
”
Build& Test
ContinuousDelivery
Deploy
Operate
Monitor &
Learn
Plan &
Track
Develop
DevOps it’s not a tool, it’s a process
Azure DevOps
Deliver value to your users faster using proven agile tools to plan, track, and discuss work across your teams.
Build, test, and deploy with CI/CD that works with any language, platform, and cloud. Connect to GitHub or any other Git provider and deploy continuously.
Get unlimited, cloud-hosted private Git repos and collaborate to build better code with pull requests and advanced file management.
Test and ship with confidence using manual and exploratory testing tools.
Create, host, and share packages with your team, and add artifacts to your CI/CD pipelines with a single click.
Azure Boards Azure ReposAzure Pipelines
Azure Test Plans Azure Artifacts
https://azure.com/devops
➔
The Xamarin Show
https://channel9.msdn.com/Shows/XamarinShow