隨着 Windows 10 發佈的,將來 Windows 平臺都是統一開發模型,能夠只寫一個 Appx 包,就能夠同時部署到html
Windows/ Windowsw Phone/ Tablet /xbox ..平臺上了,咱們幾個 Windows 組的同事也是摩拳擦掌,但願寫一html5
個用戶體驗很好的客戶端。git
看了一下 MSDN 最新發布的文檔和視頻教程,這裏做爲筆記,大概總結了一下在 Windows 10上,針對 Windows 8.1github
和 WP 上的一些技術更新。web
貼一張視頻裏面聚合的路線圖:windows
文檔內容有點長,下面截取了幾處要點翻譯了一下:瀏覽器
1)經過 Windows Universal Platform(UAP)統一的 API (Windows Runtime)和一些響應式的 UI 控件,服務器
可讓你只寫一個 app ,即可以安裝到各類設備上。app
2)PC 運行的是桌面操做系統,基於傳統的桌面家族。手機、平板等設備,運行的是 mobile 操做系統,基於的是移動
設備家族。
3) Windows 10 提供了新的 universal 控件,導航面板 和開發工具來幫助你面向多種設備進行開發。例如,你能夠利用
多種不一樣屏幕的分辨率來適配你的手機或者電腦的 UI。
4)Windows Phone 上的 Pivot 控件,如今提供給了 universal 設備上
5)在 XAML 頁面可使用 StateTriggers 來觸發頁面的 visual state 變換。它能夠經過窗口尺寸的變化,來直接改變佈局、元素
的屬性,而不須要在 C# 頁面寫邏輯進行 VisualStateManager 進行管理。 (相似於 Web 上 CSS 中的 @media ,來實現響應式佈局)
6) 一個新的 UI 共享代碼的方式,XAML 文件能夠共享一個單獨的 code-behind 文件了。
7)在選擇目標設備的SDK 時,能夠直接經過 「項目」 -> 「引用」 的方式直接添加(與引用類庫相似)。添加目標設備的 SDK(選擇 Project > Add Reference >
Universal App Platform > Extensions 添加相應的 SDK)。
8)使用這個方法 ApiInformation.IsApiContractPresent (Windows.Foundation.Metadata.ApiInformation class)檢測 api 是否支持,
不只僅是使用條件編譯了。由於有的 api 只有個別設備可使用,例如,手機上的相機實體按鍵 api。
下面一些內容翻譯自視頻教程裏面的 ppt。
一、Win 8.1 工程 -> Win 10 工程的調整
1) App 生命週期、後臺任務、Tiles 和 toasts 徹底同樣
2) UAP APIs 是 Windows 8.1 WinRT APIs 的超集 (UAP : universal app platform)
3) 可使用適應性代碼(adaptive code)判斷運行的平臺,以替換預編譯語句:
例如,以前使用:
#if WINDOWS_PHONE_APP // wp 平臺的 api 調用 #elif WINDOWS_APP // win pad 平臺的 api 調用 #endif
能夠替換爲 ApiInformation 類進行判斷:
// 判斷是不是具備實體按鍵(Back鍵、Camera 鍵..) if(Windows.Foundation.Metadata.Apilnformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons")) { // Windows phone 的相關 api }
// Windows.Foundation.Metadata.ApiInformation 類提供的靜態方法:
// IsApiContractPresent // IsEnumNamedValuePresent // IsEventPresent // IsMethodPresent // IsPropertyPresent // IsReadOnlyPropertyPresent // IsTypePresent // IsWriteablePropertyPresent
4) 一些 APIs 被棄用了( 好比 phone 8.1 的文件選擇 …AndContinue APIs)
5) 桌面右側的 Charms 被移出了,因此 app 必須提供 UI 來加載 Settings、Share 和 Search。
相關代碼邏輯和以前徹底同樣,不須要修改
5) 替換一些有的工程沒有定義的系統樣式:好比: PhoneAccentBrush
6) 建立一個響應式的 UI:
Phone/narrow view:
small landscape view:
large landscape view:
8) 添加了新控件:Relative Panel、SplitView(Splitview.Content 的屬性有意設置爲 Frame)
就像 Windows10 上面的 「計算器」,就是 SplitView控件。在單擊左上角的 「漢堡包」 按鈕,彈出切換菜單:
Win pad 和 win phone 商店裏的 Xbox One SmartGlass 猜想是一個 UAP 包了,在 phone 上的效果:
二、編譯指令
// C# Syntax #if WINDOWS_PHONE_APP Windows.Phone.UI.Input.HardwareButtons.BackPressed += this.HardwareButtons_BackPressed; #endif
// C++ Syntax #if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
_backPressedEventToken = HardwareButtons::BackPressed += ref new EventHandler<BackPressedEventArgs^> (this,&NavigationHelper::HardwareButton_BackPressed); #endif
三、支持的平臺的 SDK,能夠直接經過項目引用進行添加:
四、Segoe MDL2 字體圖標資源,更豐富的圖標字體可使用:
前段時間,寫過圖標資源的文章: 0二、Universal app 中按鈕圖標使用
五、Visual State 可使用 setters 和 triggers 直接在 XAML 中進行樣式的屬性的賦值。相似於
Web 上的 CSS媒體查詢語法(好比,@media (min-width:800px) and (max-width:1200px) { ... })。
從而不須要再 C# 頁面經過 VisualStateManager 進行視圖狀態的切換。例以下面,當窗口大於 600px 時,
StackPanel 對象爲橫向佈局:
<VisualState x:Name="wideState"> <VisualState.Setters> <Setter Target="myPanel.Orientation" Value="Horizontal" /> </VisualState.Setters> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="600"/> </VisualState.StateTriggers> </VisualState>
觸發器的參數(Trigger types):
MinWindowWidth
MinWindowHeight
六、App 與 App 的通訊:
1)在 Windows 8.1 時:URI 和 Protocol Activation/Share Contract
2)在 Windows10 UAP:
a) 啓動一個指定的 app :
var options = new LauncherOptions(); options.TargetApplicationPackageFamilyName = "24919.InstapaperIt";
var launchUri = new Uri("instapaper:?AddUrl=http%3A%2F%2Fbing.com"); await Launcher.LaunchUriAsync(launchUri, options);
b) 向另外一個 app 發送數據;經過向另外一個app 發送一個文件 token 的方式,以
向另外一個 app 傳遞本身的文件:
var options = new LauncherOptions(); options.TargetApplicationPackageFamilyName = "24919.InstapaperIt"; var token = SharedStorageAccessManager.AddFile(gpxFile); ValueSet inputData = new ValueSet(); inputData.Add("Token", token); var launchUri = new Uri("instapaper:?AddUrl=http%3A%2F%2Fbing.com"); await Launcher.LaunchUriAsync(launchUri, options, inputData);
c) Launch for Results:啓動另外一個 app,並得到其返回結果:
// 一個 app var options = new LauncherOptions(); options.TargetApplicationPackageFamilyName = "24919.Instap"; var launchUri = new Uri("instapaper:?AddUrl=http%3A%2F%2Fbing.com"); await Launcher.LaunchUriForResultsAsync(launchUri, options, data); // 另外一個 app,把結果存到 ValueSet 字典中,返回 var resultData = new ValueSet(); resultData.Add("Result", value); operation.ProtocolForResultsOperation.ReportCompleted(resultData);
d) 判斷當前設備上是否有指定 app (Query URI Support. Discover if app already installed to handle a Uri):
// 判斷當前設備上,是否有 app 聲明瞭instapaper 啓動協議名稱 var queryUri = new Uri("instapaper:"); await Launcher.QueryUriSupportAsync(queryUri, LaunchUriType.LaunchUri); // 判斷當前設備上,是否有 app 聲明瞭instapaper 啓動協議名稱,而且它的 pfn 爲 "24919.InstapaperIt" 的指定app var queryUri = new Uri("instapaper:"); string packageFamilyName = "24919.InstapaperIt"; await Launcher.QueryUriSupportAsync(queryUri, LaunchUriType.LaunchUriForResults, packageFamilyName);
e) 來自同一個發佈者(同一個開發者帳號)的多個 app,可 Share 同一個存儲文件夾 和設置(files and settings)。
須要在 app 的清單件中聲明一個子文件夾,當系統安裝 app 時,會自動建立的:
<Package> <Extensions> <Extension Category="windows.publisherCacheFolder"> <PublisherCacheFolder> <Folder Name="folder1"> </PublisherCacheFolder> </Extension> </Extensions> </Package>
在 app 中獲取這個文件夾:
// 獲取這個共享的文件夾 Windows.Storage.ApplicationData.Current.GetPublisherCacheFolder("folder1"); // 清空共享文件夾 Windows.Storage.ApplicationData.Current.ClearPublisherCacheFolderAsync();
e) App Services:經過後臺任務的方式,一個app 能夠做爲一個本地輕量級的 Web Service
供其它 app 調用。
七、Drag 和 drop
在之前的 XAML 上,拖、拽操做比較侷限,只有特定控件(GridView、ListView)有拖拽事件:
<GridView AllowDrop="true" DragEnter="contactGridView_DragEnter" DragLeave="contactGridView_DragLeave" DragOver="contactView_DragOver" Drop="contactGridView_Drop"/>
在 UAP 上添加了新的拖、拽 API,能夠實現 app 之間的拖放,好比:
1)ListViewBase.DragItemsCompleted
2)UIElement.DragAsync()
3)擴展的 DragEventArgs 參數
八、編譯時的數據綁定
XAML 中的 Data Binding 會影響性能,動態類型和反射是部分緣由。解決方案是編譯時(Compile-time binding)
的綁定。優勢是全面快速的實例化,高效的 change 偵測和 UI 更新,編譯時錯誤(Compile-time errors)
<!--示例--> <ListView ItemsSource="{x:Bind Groups}" > <ListView.ItemTemplate> <DataTemplate TargetType="data:BookItem" > <TextBlock Text="{x:Bind Book.Title}" /> </DataTemplate> </ListView.ItemTemplate> </ListView>
九、Transform 3D, 很像 CSS 中的 「preserve-3d」
Transform 3D 不會影響子元素的 transforms
1)現有的變換屬性(Composite transform):
Translate Transform (move)
Scale Transform (size)
Rotate Transform (angle)
Skew Transform (shape)
Render Origin
利用 Projection 屬性(Rotate X/Y/Z) 模擬 3D 效果
2) UAP 中添加了新屬性 UIElement.Transform3D:
容器:
Container.PerspectiveTransform3D
Depth
OffsetX
OffsetY
子元素:
Child.CompositeTransform3D
Rotation
Scale
Translate
<Grid Width="300" Height="200"> <Grid.Transform3D> <PerspectiveTransform3D OffsetX="-150" OffsetY="-100" Depth="1000" /> </Grid.Transform3D> <Grid Background="Red"> <Grid.Transform3D> <CompositeTransform3D RotationY="30" TranslateZ="1"/> </Grid.Transform3D> </Grid> <Grid Background="Blue"> <Grid.Transform3D> <CompositeTransform3D RotationX="-30" TranslateZ="-1"/> </Grid.Transform3D> </Grid> </Grid>
十、 App Services:
1) UAP 提供了不少 API 來使 app 之間互相通訊:
Windows.ApplicationModel.Contacts
Windows.ApplicationModel.Email
Windows.System.Launcher.LaunchUriAsync 啓動h settings, maps, store 等…
其它…
2)UAP 容許 app 之間互相通訊:
· Uri 關聯,使用 LaunchUriAsync 啓動
· File 關聯,使用 LaunchFileAsync 啓動
· Launch 並獲取結果,使用 LaunchUriForResultsAsync
· App Services:用來做爲靈活、輕量級的,相似於 web REST 服務:
a、簡單的請求、響應消息 api
b、以 string-keyed 形式(ValueSet 類型) 數據包傳遞
c、易於使用和多個不一樣的載荷
3)App Services – Client 示例:
AppServiceConnection connection = new AppServiceConnection(); connection.AppServiceName = "microsoftDX-appservicesdemo"; connection.PackageFamilyName = "24919ArunjeetSingh.InstapaperIt"; AppServiceConnectionStatus connectionStatus = await connection.OpenAsync(); if (connectionStatus == AppServiceConnectionStatus.Success) { //向服務端發送數據 var message = new ValueSet(); message.Add("Command", "CalcSum"); message.Add("Value1", Int32.Parse(Value1.Text)); message.Add("Value2", Int32.Parse(Value2.Text)); // 發送消息並等待響應 AppServiceResponse response = await connection.SendMessageAsync(message); if (response.Status == AppServiceResponseStatus.Success) { int sum = (int)response.Message["Result"]; new MessageDialog("Result=" + sum).ShowAsync(); } } else { //若是沒有 app service 端,則指導用戶下載 app service 端 }
App Services – Service:
namespace AppServicesDemoTask { // 須要繼承 IBackgroundTask 接口 public sealed class AppServiceTask : IBackgroundTask { private static BackgroundTaskDeferral _serviceDeferral; public void Run(IBackgroundTaskInstance taskInstance) { // 註冊當先後臺任務的 取消事件 taskInstance.Canceled += TaskInstance_Canceled; // 得到任務實例的 deferal 對象 _serviceDeferral = taskInstance.GetDeferral(); var appService = taskInstance.TriggerDetails as AppServiceTriggerDetails; if (appService.Name == "microsoftDX-appservicesdemo") { // 能夠添加調用 app 的合法性驗證 ValidateCaller(appService.CallerPackageFamilyName) ?? appService.AppServiceConnection.RequestReceived += RequestReceived; } } ... private async void RequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args) { var message = args.Request.Message; // 服務端使用 Command 參數,做爲 client 調用的操做 string command = message["Command"] as string; switch (command) { case "DoIt": { var messageDeferral = args.GetDeferral(); int value1 = (int)message["Value1"]; // ... 作一些處理 //向調用者返回結果 var returnMessage = new ValueSet(); returnMessage.Add("Result", result); var responseStatus = await args.Request.SendResponseAsync(returnMessage); messageDeferral.Complete(); break; } case "Quit": { // 服務端被要求退出,則調用deferral 對象的 Complete 方法,系統終止 Service _serviceDeferral.Complete(); break; } } }
4) 在清單文件中聲明 App Service:
<?xml version="1.0" encoding="utf-8"?> <Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"> <Applications> <Application Id="App「> <Extensions> <uap:Extension Category="windows.appService「 EntryPoint="AppServicesDemoTask.AppServiceTask"> <uap:AppService Name="microsoftDX-appservicesdemo" /></uap:Extension> </Extensions> </Application> </Applications> <Capabilities> <Capability Name="internetClient" /> </Capabilities> </Package>
5)雙向通訊 :Client 和 server 均可以發送和接收消息
Client 和 server 能夠保持雙向通訊的 channel 打開着。Client 端能夠給本身
AppServiceConnection 實例註冊一個 RequestReceived 事件
AppServiceConnectionStatus connectionStatus = await connection.OpenAsync(); if (connectionStatus == AppServiceConnectionStatus.Success) { connection.RequestReceived += OnRequestReceived; }
6)在調試的時候能夠經過 Package.Current.Id.FamilyName 屬性得到包的 PFN:
7)App Service 生命週期:
· Server 端的後臺任務經過設置 AppServiceTrigger 條件啓動
· Client 端能夠經過調用 AppServiceConnection 對象的 dispose方法,或者發送指示命令來關閉 Service 端
· 若是 Client 端被掛起,則相應的 Service app 會被關閉
· 當系統資源緊張會致使 Launch 失敗或者 Service 被關閉:服務端得到 AppServiceConnectionStatus.ResourcesNotAvailable消息;
當發送消息時得到 AppServiceResponseStatus.ResourceLimitsExceeded
十一、消息中心 Action Center Management APIs:
1)管理 app 的通知,開發者能夠:
· 移出一個或多個通知
· 給 notification 通知添加標籤和分組
· 替換爲一個新的 notification
· 設置一個 notification 的過時時間
· 發送一個 「Ghost Toast」 notification(只顯示在通知中心,但不彈給用戶)
2)每一個 app 最多在通知中心有 20條通知。最長保存7天(或者更短)
用戶能夠:
· 追蹤(單擊)一個通知(從通知中心移出)
· 移出一組通知
· 移出全部通知
3)後臺任務觸發器(ToastNotificationHistoryChangedTrigger)
當用戶從消息中心解除一個 notification 或者一個 app 添加、移出、替換
一個notification 時觸發。
使用這個觸發器任務,app 能夠保持 Toast 、Tile 消息通知的一致性。好比,
用戶移出了消息中心的 通知時,tile 上的相關消息也須移出:
// 使用 ToastNotificationHistoryChangedTrigger 觸發器的後臺任務 public sealed class ActionCenterChangedTask: IBackgroundTask { public void Run(IBackgroundTaskInstance taskInstance) { var toasts = ToastNotificationManager.History.GetHistory(); if (toasts != null) { var count = toasts.Count(); if (count== 0) { BadgeUpdateManager.CreateBadgeUpdaterForApplication().Clear(); } else { XmlDocument badgeXml = BadgeUpdateManager.GetTemplateContent(BadgeTemplateType.BadgeNumber); XmlElement badgeElement = (XmlElement)badgeXml.SelectSingleNode("/badge"); badgeElement.SetAttribute("value", count.ToString()); BadgeNotification badge = new BadgeNotification(badgeXml); BadgeUpdateManager.CreateBadgeUpdaterForApplication().Update(badge); } } } }
十二、Web 平臺(Sparta 瀏覽器)
有關 Web 更新有不少,具體視頻上講的很詳細。這裏只列出一點。
從 Windows 8 開始,已經可使用 html5/js 的方式開發 native app 了,而且不是經過 WebView 控件,
而是直接經過 JS 調用 Windows Runtime 的 api,可是不容許從 appx 包外的 JS 調用。到了 Windows 10
的 UAP,則去掉了這個限制,甚至能夠經過在 app 的清單文件中,指定服務器端的地址,直接下載到本地執行邏輯,
調用 runtime 的 api。經過這種方式,很容易實現各類功能擴展。
清單文件添加服務器端的地址:
<uap:ApplicationContentUriRules> <uap:Rule Type="include" WindowsRuntimeAccess="all" Match="https://rjs.azurewebsites.net/" /> <uap:Rule Type="include" WindowsRuntimeAccess="allowForWebOnly" Match="https://*.facebook.com/" /> <uap:Rule Type="include" WindowsRuntimeAccess="none" Match="http://bing.com/" /> <uap:Rule Type="include" Match="https://*.microsoft.com/" /> </uap:ApplicationContentUriRules>
W3C 標準 Manifest for Web Apps:http://w3c.github.io/manifest/