take a ride on the metro
DESCRIPTION
More info on http://www.techdayTRANSCRIPT
Take a Ride on the Metro Jeff
ProsiseCofounderWintellect
What is Metro?A new shell for Windows 8Runs immersive apps ("Metro apps") distributed through Windows StoreRuns on Intel processors and ARM processorsTouch-first, but with support for mouse and stylusRich API for shell integration (tiles, toasts, etc.)
A new programming model for developersXAML + C#/C++/VB, orHTML5 + JavaScript
Windows 8 Architecture
The Windows Runtime (WinRT)New API for Metro-style appsWin32 is old, complicated, and built for C/C++WinRT is new, simpler, and language-agnostic
APIs for storage, networking, and much moreMore than 100 namespaces, thousands of types
I/O is asynchronous (> 50 ms)C# await keywordJavaScript promises (.then)
Creating a File (.NET/C#)string path = Environment.GetFolderPath
(Environment.SpecialFolder.MyDocuments) + "\\Sample.txt";
using (StreamWriter writer = new StreamWriter(path))
{
writer.WriteLine("Hello, .NET");
}
Creating a File (WinRT/C#)var folder = KnownFolders.DocumentsLibrary;
var file = await folder.CreateFileAsync("Sample.txt");
var ras = await file.OpenAsync(FileAccessMode.ReadWrite);
using (Stream stream = ras.OpenWrite())
{
using (StreamWriter writer = new StreamWriter(stream))
{
writer.WriteLine("Hello, Metro");
}
}
Creating a File (WinRT/JavaScript)var folder = Windows.Storage.KnownFolders.documentsLibrary;
folder.createFileAsync("Sample.txt").then(function (file) {
file.OpenAsync(Windows.Storage.FileAccessMode.readWrite).then(function (ras) {
var stream = ras.openWrite();
var writer = new Windows.Storage.Streams.DataWriter(stream);
writer.writeString("Hello, Metro");
writer.storeAsync().then(function () {
stream.flushAsync().then(function () { });
});
});
});
DemoYour First Metro Application
Pointer InputWindows 8 is a "touch-first" operating systemWindows.UI.Xaml.UIElement defines events for processing pointer input (including touch input)Pointer events for low-level input (e.g., pressed)Tap events for taps and other simple gesturesManipulation events for dragging and pinchingInertia support built in
PointerDeviceType identifies pointer type (touch, stylus, or mouse) except on manipulation events
Pointer EventsEvent Description
PointerCanceled Fired when the pointer loses contact "abnormally"
PointerCaptureLost Fired when a UI element loses pointer capture
PointerEntered Fired when the pointer enters a UI element
PointerExited Fired when the pointer exits a UI element
PointerMoved Fired when the pointer moves over a UI element
PointerPressed Fired when the pointer is pressed over a UI element
PointerReleased Fired when the pointer is released over a UI element
PointerWheelChanged
Fired when the mouse wheel is rolled
Detecting Mouse Clicks// XAML
<Rectangle Width="100" Height="100" Fill="Red" PointerPressed="OnPressed" />
// C#
void OnPressed(Object sender, PointerEventArgs e)
{
PointerPoint point = e.GetCurrentPoint((UIElement) sender);
// Change Rectangle's fill color to yellow on mouse click
if (point.PointerDevice.PointerDeviceType == PointerDeviceType.Mouse)
((Rectangle) sender).Fill = new SolidColorBrush(Colors.Yellow);
// Get coordinates where event occurred
double x = point.Position.X;
double y = point.Position.Y;
}
Tap EventsEvent Description
Tapped Fired when a UI element is tapped
DoubleTapped Fired when a UI element is double-tapped
RightTapped Fired when a UI element is right-tapped (mouse only)
Holding Fired when a UI element is tapped and held
Detecting Tap Gestures// XAML
<Rectangle Width="100" Height="100" Fill="Red" Tapped="OnTapped" />
// C#
void OnTapped(Object sender, TappedEventArgs e)
{
// Change Rectangle's fill color to yellow when tapped
((Rectangle) sender).Fill = new SolidColorBrush(Colors.Yellow);
// Get tap coordinates
double x = e.GetPosition((UIElement) sender).X;
double y = e.GetPosition((UIElement) sender).Y;
}
Manipulation EventsEvent Description
ManipulationStarting Fired when a manipulation is about to start
ManipulationStarted Fired when a manipulation begins
ManipulationDelta Fired when a manipulation continues
ManipulationCompleted Fired when a manipulation ends
ManipulationInertiaStarting
Fired when a manipulation ends and the finger was still moving when it broke contact with the screen
Moving and Scaling a UI Element// XAML
<Rectangle ... ManipulationDelta="OnManipulationDelta" ManipulationMode="All">
<Rectangle.RenderTransform>
<CompositeTransform x:Name="RectTransform" />
</Rectangle.RenderTransform>
</Rectangle>
// C#
void OnManipulationDelta(Object sender, ManipulationDeltaEventArgs e)
{
RectTransform.TranslateX += e.DeltaManipulation.Translation.X;
RectTransform.TranslateY += e.DeltaManipulation.Translation.Y;
RectTransform.ScaleX *= e.DeltaManipulation.Scale;
RectTransform.ScaleY *= e.DeltaManipulation.Scale;
}
DemoPointer Input
Application LifecycleMetro apps run one at a timeApps not in the foreground are suspendedApplication.Suspending event precedes suspensionSuspended apps may be terminatedHandle Suspending event and save state in application data (Windows.Storage.ApplicationData)
Apps are resumed when (if) user switches backOverride Application.OnLaunched and restore state if app was suspended and terminated
Saving State in SettingsApplication.Current.Suspending += (s, e) =>
{
// Persist the TextBox named "Input" in LocalSettings
ApplicationData.Current.LocalSettings.Values["Input"] = Input.Text;
// Or persist it in RoamingSettings
ApplicationData.Current.RoamingSettings.Values["Input"] = Input.Text;
};
Restoring State from Settings// App.xaml.csprotected override void OnLaunched(LaunchActivatedEventArgs e){ Window.Current.Content = new MainPage(e.Kind == ActivationKind.Launch && e.PreviousExecutionState == ApplicationExecutionState.Terminated); Window.Current.Activate();}
// MainPage.xaml.cspublic MainPage(Boolean restore){ InitializeComponent(); if (restore) Input.Text = ApplicationData.Current.LocalSettings.Values["Input"] ?? String.Empty;}
The Resuming Event
Fired when app is resumed following suspension• Fired after Application.OnLaunched is called• Fired regardless of whether app was terminated• Receives no information indicating whether app was
terminated; not a replacement for OnLaunchedUse Resuming events to update state that might have gotten stale while app was suspended
Using Resuming EventsApplication.Current.Resuming += (s, e) =>
{
// TODO: Freshen stale state
}
DemoProgram Lifecycle Management (PLM)
ContractsContracts allow apps to integrate with charmsCharms provide unified and predictable way for users to access common features such as search and settings
Three types of contractsSharing – Share data using Share charmSearch – Search for data using Search charmSettings – Edit application settings and user preferences through Settings charm
Essential part of Metro UI
SharingAllows sharing of data between appsSource app registers handler for DataRequested event fired when user taps share charmHandler receives DataPackage and writes data to itText, RTF, HTML, URI, Bitmap, and StorageItems
Target app selected by user is launched by OSPassed a ShareOperation containing a DataPackageTarget retrieves data from the DataPackage
Think of it as the "Metro clipboard"
Sharing TextDataTransferManager.GetForCurrentView().DataRequested += (s, e) =>
{
DataPackage dp = e.Request.Data;
dp.Properties.Title = "This is my title";
dp.Properties.Description = "This is my description";
dp.RequestedOperation = DataPackageOperation.Copy;
dp.SetText("Hello, Metro");
}
Sharing an ImageDataTransferManager.GetForCurrentView().DataRequested += (s, e) =>
{
DataPackage dp = e.Request.Data;
dp.Properties.Title = "This is my title";
dp.Properties.Description = "This is my description";
dp.RequestedOperation = DataPackageOperation.Copy;
DataRequestDeferral deferral = e.Request.GetDeferral();
StorageFile file = await KnownFolders.DocumentsLibrary.GetFileAsync("Image.jpg");
IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read);
dp.SetBitmap(stream);
deferral.Complete();
}
Consuming a Shared Imagepublic void Activate(ShareTargetActivatedEventArgs args){ Window.Current.Content = this; Window.Current.Activate();
var op = args.ShareOperation; string title = op.Data.Properties.Title; string description = op.Data.Properties.Description; BitmapImage bi = new BitmapImage(); bi.SetSource(op.Data.GetBitmap()); XamlImage.Source = bi; // Display the image
ShareButton.Click += (s, e) => { op.ReportCompleted(); };}
DemoSharing
TilesEvery app has a primary tileCreated when app is installed; can be square or wide
App can also create secondary tilesAct as shortcuts into a Metro appActivate app in a predetermined state
Each secondary tile has an ID and argumentsSpecified when tile is createdArguments passed in LaunchActivatedEventArgs when app is launched (Application.OnLaunched)
Tile UpdatesTiles can be updated with live contentTileUpdateManager factory class creates TileUpdatersTileUpdater.Update updates a tile's content
Tile updates can be queued or non-queuedTileUpdater.EnableNotificationQueue enables queuingUp to five notifications can be queued; system rotates queued updates
Tiles can also be updated by push notifications transmitted by Windows Push Notification Service
Updating a Tilevar tu = TileUpdateManager.CreateTileUpdaterForApplication();
XmlDocument tileXml = ...; // XML for wide and small tiles
var tn = new TileNotification(tileXml) {
ExpirationTime = DateTimeOffset.UtcNow.AddSeconds(10), Tag = "MyTag"
};
tu.Update(tn);
Secondary TilesEvery app has a primary tileCreated when app is installed
App can also create secondary tilesAct as shortcuts into a Metro appActivate app in a predetermined state
Each secondary tile has an ID and argumentsSpecified when tile is createdArguments passed in LaunchActivatedEventArgs when app is launched (Application.OnLaunched)
Creating a Secondary Tilevar tile = new SecondaryTile(
"MSFT", // App-defined tile ID
"Microsoft", // Short name
"Microsoft", // Display name
"Args", // App-defined activation args
TileDisplayAttributes.ShowName, // Display attributes
new Uri("ms-resource:Images/Logo.png"), // Square (150x150) tile URI
new Uri("ms-resource:Images/Wide.png") // Wide (310x150) tile URI
);
bool approved = await tile.RequestCreateAsync();
Retrieving Arguments at Launch// App.xaml.cs
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Window.Current.Content = new MainPage(e.Arguments);
Window.Current.Activate();
}
// MainPage.xaml.cs
public MainPage(args)
{
InitializeComponent();
// TODO: Initialize app based on args parameter
}
Updating a Secondary Tilevar tu = TileUpdateManager.CreateTileUpdaterForSecondaryTile();
XmlDocument xml = ...; // XML for wide and small tiles
var tn = new TileNotification(xml) {
ExpirationTime = DateTimeOffset.UtcNow.AddSeconds(10), Tag = "MyTag"
};
tu.Update(tn);
DemoSecondary Tiles
Download the Code
http://www.wintellect.com/downloads/metro.zip
Be what’s next: Windows 8 Metro Apps• Find everything here
http://aka.ms/mbl-win8• Save the date! March 23: Windows 8 Developer Day
and “Nacht van Windows 8 / La Nuit de Windows 8 (app-a-thon coding night)
• Start today!• Building Windows 8 blog: http://aka.ms/mbl-win8/build• Learn with Windows 8 Dev Preview: http://aka.ms/mbl-win8/devprev • Learn about Windows Store and opportunities:
http://aka.ms/mbl-win8/store
© 2012 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.