共用合約是 Windows 8 特有的應用間資料交換機制。使用者從任意應用呼叫「共用」Charm,選擇目標應用接收資料。本文完整實作共用來源(提供資料)、共用目標(接收處理)、QuickLink(快捷共用)與應用啟動整合。
| 角色 | 核心類別 | 關鍵流程 |
|---|---|---|
| 共用來源 | DataTransferManager、DataPackage | DataRequested 事件 → 填充 DataPackage → 系統顯示共用面板 |
| 共用目標 | ShareOperation、DataPackageView | App.xaml.cs OnShareTargetActivated → 解析 DataPackageView → ReportCompleted |
| QuickLink | QuickLink | 目標端 ReportCompleted(quickLink) → 來源面板顯示快捷項 → 再次啟動攜帶 QuickLinkId |
protected override void OnNavigatedTo(NavigationEventArgs e) {
var dtm = DataTransferManager.GetForCurrentView();
dtm.DataRequested += OnDataRequested;
dtm.TargetApplicationChosen += OnTargetChosen;
}
private void OnTargetChosen(DataTransferManager sender, TargetApplicationChosenEventArgs args) {
lblStatus.Text = $"共用給: {args.ApplicationName}";
}
private void OnDataRequested(DataTransferManager sender, DataRequestedEventArgs args) {
var request = args.Request;
var data = request.Data;
data.Properties.Title = "標題";
data.Properties.Description = "描述";
switch (_shareType) {
case "Share Text":
data.SetText("需要分享的詳細內容");
break;
case "Share Link":
data.SetUri(new Uri("https://webabcd.cnblogs.com"));
break;
case "Share Image":
var imgRef = RandomAccessStreamReference.CreateFromFile(_selectedFiles.First());
data.Properties.Thumbnail = imgRef;
data.SetBitmap(imgRef);
break;
case "Share File":
data.SetStorageItems(_selectedFiles);
break;
case "Share Html":
string html = "webabcd
";
data.SetHtmlFormat(HtmlFormatHelper.CreateHtmlFormat(html));
data.ResourceMap["ms-appx:///Assets/Logo.png"] =
RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/Logo.png"));
break;
case "Share Custom Data":
data.SetData("https://webabcd/sharedemo", "自訂資料內容");
break;
case "Share With Deferral":
data.Properties.Thumbnail = RandomAccessStreamReference.CreateFromFile(_selectedFiles.First());
data.SetDataProvider(StandardDataFormats.Bitmap, OnDeferredImageRequested);
break;
}
}
資料生成耗時(如大圖壓縮)時,使用 SetDataProvider 註冊提供者,使用者選擇目標後才執行:
private async void OnDeferredImageRequested(DataProviderRequest request, StorageFile imageFile) {
var deferral = request.GetDeferral();
try {
using (var stream = await imageFile.OpenAsync(FileAccessMode.Read)) {
var decoder = await BitmapDecoder.CreateAsync(stream);
var memStream = new InMemoryRandomAccessStream();
var encoder = await BitmapEncoder.CreateForTranscodingAsync(memStream, decoder);
encoder.BitmapTransform.ScaledWidth = (uint)(decoder.OrientedPixelWidth * 0.5);
encoder.BitmapTransform.ScaledHeight = (uint)(decoder.OrientedPixelHeight * 0.5);
await encoder.FlushAsync();
// 模擬長時間處理
await Task.Delay(3000);
request.SetData(RandomAccessStreamReference.CreateFromStream(memStream));
}
} finally {
deferral.Complete();
}
}
protected override void OnShareTargetActivated(ShareTargetActivatedEventArgs args) {
var rootFrame = new Frame();
rootFrame.Navigate(typeof(ShareTargetPage), args);
Window.Current.Content = rootFrame;
Window.Current.Activate();
}
在「宣告」頁籤新增「共用目標」,勾選支援的資料格式:文字、URI、HTML、位圖、儲存項目、自訂格式(需填入格式識別碼如 https://webabcd/sharedemo)。
protected async override void OnNavigatedTo(NavigationEventArgs e) {
var args = (ShareTargetActivatedEventArgs)e.Parameter;
_shareOperation = args.ShareOperation;
await Task.Run(async () => {
// 基本屬性
ShowMessage($"QuickLinkId: {_shareOperation.QuickLinkId}");
ShowMessage($"Title: {_shareOperation.Data.Properties.Title}");
ShowMessage($"Description: {_shareOperation.Data.Properties.Description}");
await ShowThumbnail(_shareOperation.Data.Properties.Thumbnail);
// 依格式解析
var data = _shareOperation.Data;
if (data.Contains(StandardDataFormats.Text)) {
ShowMessage($"Text: {await data.GetTextAsync()}");
}
if (data.Contains(StandardDataFormats.Uri)) {
ShowMessage($"Uri: {(await data.GetUriAsync()).AbsoluteUri}");
}
if (data.Contains(StandardDataFormats.Bitmap)) {
await ShowBitmap(await data.GetBitmapAsync());
}
if (data.Contains(StandardDataFormats.Html)) {
ShowMessage($"Html: {await data.GetHtmlFormatAsync()}");
var resourceMap = await data.GetResourceMapAsync(); // 取得本地資源引用
}
if (data.Contains(StandardDataFormats.StorageItems)) {
foreach (var item in await data.GetStorageItemsAsync()) {
ShowMessage($"File: {item.Path}");
}
}
if (data.Contains("https://webabcd/sharedemo")) {
ShowMessage($"Custom: {await data.GetTextAsync("https://webabcd/sharedemo")}");
}
});
}
private async void OnCompleteClick(object sender, RoutedEventArgs e) {
var quickLink = new QuickLink {
Id = "預定義資料,避免使用者重複輸入",
Title = "快捷共用標題",
Thumbnail = RandomAccessStreamReference.CreateFromFile(
await Package.Current.InstalledLocation.GetFileAsync("Assets\\Logo.png")),
SupportedFileTypes = { "*" },
SupportedDataFormats = {
StandardDataFormats.Text, StandardDataFormats.Uri,
StandardDataFormats.Bitmap, StandardDataFormats.StorageItems,
StandardDataFormats.Html, "https://webabcd/sharedemo"
}
};
_shareOperation.ReportCompleted(quickLink); // 完成並新增 QuickLink
}
QuickLink 讓使用者一鍵重複共用給相同目標(如固定郵件收件者、社群帳號)。生命週期:
ReportCompleted(quickLink) 時建立ShareOperation.QuickLinkId 攜帶預定義 IdQuickLinkId 直接執行動作(如自動填入收件者)RemoveThisQuickLink()| 格式 | StandardDataFormats | 來源 Set 方法 | 目標 Get 方法 | 備註 |
|---|---|---|---|---|
| 文字 | Text | SetText | GetTextAsync | 最基礎格式 |
| 連結 | Uri | SetUri | GetUriAsync | 單一 URI |
| HTML | Html | SetHtmlFormat | GetHtmlFormatAsync | 需 HtmlFormatHelper 封裝,ResourceMap 傳遞本地圖片 |
| 位圖 | Bitmap | SetBitmap | GetBitmapAsync | RandomAccessStreamReference |
| 檔案 | StorageItems | SetStorageItems | GetStorageItemsAsync | IReadOnlyList |
| RTF | Rtf | SetRtf | GetRtfAsync | 富文本格式 |
| 自訂 | 自訂字串 | SetData | GetDataAsync | 需雙方約定,Manifest 宣告 |
DataRequested 事件中填充 DataPackage,不可預先建立(資料可能過時)。SetDataProvider 延遲渲染,避免共用面板開啟延遲。ResourceMap,否則目標端無法解析圖片。OnNavigatedTo 中務必 await 所有 GetXxxAsync,切勿同步阻塞。ReportCompleted()(可選 QuickLink),否則共用面板不會關閉。ReportStarted()、ReportDataRetrieved()、ReportSubmittedBackgroundTask() 讓系統優化資源。SupportedDataFormats/SupportedFileTypes 需與目標端實際支援一致,不匹配則不顯示。DataPackage 同時服務於共用合約與剪貼簿。同一份資料準備邏輯可同時支援「複製」與「共用」兩種使用者意圖,只需分別呼叫 Clipboard.SetContent() 與 DataTransferManager.ShowShareUI()。
完整實作共用合約,能讓你的應用無縫融入 Windows 8 的應用生態系統,成為資料流動的來源或目的地。