Win10/UWP新特性—Drag&Drop 拖出元素到其餘App

    在之前的文章中,寫過微軟新特性Drag&Drop,當時可能因爲處於Win10預覽版,使用的VS也是預覽版,只實現了從桌面拖拽文件到UWP App中,沒能實現從UWP拖拽元素到Desktop App & UWP App中。昨天從新研究了Win10 拖拽這一塊,發現之前沒能實現的功能,在正式版的環境下均可以實現了,作個筆記以防往後忘記。html

    在UWP中,想要拖動元素到Desktop或者另外一個UWP App中,除了設置元素的CanDrag="True"咱們要使用元素的DragStarting事件,CanDrag屬性設置元素能被拖動,DragStarting事件中咱們即可覺得拖動準備數據,改變拖動時的UI等一些操做。app

    咱們依然使用上篇Drag&Drop文章中例子,在底部新增一個Img元素,設置以下:dom

1 <Image  x:Name="img" 
2         CanDrag="True"
3         Source="Assets/I Am 1%.jpg"
4         DragStarting="Image_DragStarting"/>

咱們要用到事件的DragStartingEventArgs參數,在該參數中咱們能夠爲拖動準備拖動的數據,更改UI設置,其中有幾個重要的屬性和方法:async

<!--/* DragStartingEventArgs.Data中能夠設置不少類型的數據:

        ·public void SetBitmap(RandomAccessStreamReference value); 設置 DataPackage 中包含的位圖圖像。
        
        ·public void SetData(System.String formatId, [HasVariant] System.Object value); 設置 RandomAccessStream 格式的 DataPackage 中包含的數據。
        
        ·public void SetHtmlFormat(System.String value); 向 DataPackage 添加 HTML 內容。
        
        ·public void SetRtf(System.String value); 設置 DataPackage 中包含 RTF 格式內容。
        
        ·public void SetStorageItems(IEnumerable<IStorageItem> value); 設置存儲對象
        
        ·public void SetStorageItems(IEnumerable<IStorageItem> value, System.Boolean readOnly);設置存儲對象 只讀模式
        
        ·public void SetText(System.String value); 設置 DataPackage 包含的文本。
        
        ·public void SetUri(Uri value); 設置一個Uri
        
        ·public void SetWebLink(Uri value); 設置一個WebLink
        
        //設置拖動時的圖標
        
        ·args.DragUI.SetContentFromBitmapImage     設置一個bitmap圖片
        
        ·args.DragUI.SetContentFromDataPackage(); 設置來源於拖動的數據
        
         
        
        注:
        
        拖動源設置了相應的數據類型後,若是拖動元素到另外一個UWP App中(接收者),
        
        則接收者須要根據相應的數據類型才能取出數據,
        
        若是不肯定數據類型可使用DragEventArgs參數的DataView.Contains(StandardDataFormats formats)方法來肯定是否包含某種數據類型
        
        而後再進行取出,沒有判斷直接強制取出,若是類型不匹配接收者會報錯

*/-->

咱們在DragStarting事件中處理拖動以下:ide

private async void Image_DragStarting(UIElement sender, DragStartingEventArgs args)
{
    //設置預覽拖動時的圖標 來源於數據
    args.DragUI.SetContentFromDataPackage();
 
    // 設置一個圖片替換拖動時的圖標
    // args.DragUI.SetContentFromBitmapImage(new BitmapImage(new Uri("ms-appx:///Assets/Data-Export.png")) { DecodePixelWidth = 48, DecodePixelHeight = 48 },new Point(0,0));
 
    // 拖動的行爲,這裏選擇Copy 注意,若是選擇 Move,拖動完成後會刪除源文件
    args.Data.RequestedOperation = DataPackageOperation.Copy;
 
    /*  DragStartingEventArgs.Data中能夠設置不少類型的數據:
        ·public void SetBitmap(RandomAccessStreamReference value);      設置 DataPackage 中包含的位圖圖像。
        ·public void SetData(System.String formatId, [HasVariant] System.Object value);     設置 RandomAccessStream 格式的 DataPackage 中包含的數據。
        ·public void SetHtmlFormat(System.String value);     向 DataPackage 添加 HTML 內容。
        ·public void SetRtf(System.String value);       設置 DataPackage 中包含 RTF 格式內容。
        ·public void SetStorageItems(IEnumerable<IStorageItem> value); 設置存儲對象
        ·public void SetStorageItems(IEnumerable<IStorageItem> value, System.Boolean readOnly);設置存儲對象 只讀模式
        ·public void SetText(System.String value);  設置 DataPackage 包含的文本。
        ·public void SetUri(Uri value);     設置一個Uri
        ·public void SetWebLink(Uri value);     設置一個WebLink
 
        注:
        拖動源設置了相應的數據類型後,若是拖動元素到另外一個UWP App中(接收者),
        則接收者須要根據相應的數據類型才能取出數據,
        若是不肯定數據類型可使用DragEventArgs參數的DataView.Contains(StandardDataFormats formats)方法來肯定是否包含某種數據類型
        而後再進行取出,沒有判斷直接強制取出,若是類型不匹配接收者會報錯
    */
 
 
    // 設置拖動data 添加一些StorageItems數據,這裏取一些img圖片,這些圖片拖動後會copy到拖動目標上
    // 若是拖動到桌面文件夾,則會copy文件到文件夾
    var folder = await Package.Current.InstalledLocation.GetFolderAsync(@"Imgs");
    args.Data.SetStorageItems(await folder.GetFilesAsync());
 
    // 設置BitMap數據  
    var sf = await Package.Current.InstalledLocation.GetFileAsync(@"Assets\I Am 1%.jpg");
    args.Data.SetBitmap(RandomAccessStreamReference.CreateFromFile(sf));
}

上面咱們一共設置兩種數據,第一種是經過args.Data.SetStorageItems()方法將指定文件夾下的圖片賦值到拖動Data上,第二種咱們經過args.Data.SetBitmap()方法設置了一個圖片到Data的BitMap中。學習

使用時,咱們在拖動元素到另外一個App(接收者)中時,就要根據上面具體設置的數據類型來獲取到相應的數據。spa

接下來咱們建立一個新的UWP App(接收者) ,界面上放置一個ListView,並設置可接受拖動數據,而後訂閱相關的拖動事件以下:code

1 <Grid x:Name="MainGrid"  
2     AllowDrop="True"   
3     Drop="VcBorder_Drop"
4     DragOver="VcBorder_DragOver"
5       Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
6     <ListView Margin="8" x:Name="ImgList"/>
7 </Grid>

咱們要實現的功能就是,從一個App中拖動元素到這個App中,拖動完成後獲取拖動數據(一組圖片和一個BitMap對象),獲取的圖片添加到ListView中,獲取的BitMap對象則給Grid容器的背景色賦值。orm

DragOver事件中,咱們能夠更改拖動元素到目標範圍內時的UI外觀,定製以下:htm

1 private void VcBorder_DragOver(object sender, DragEventArgs e)
2 {
3     Debug.WriteLine("[Info] DragOver");
4     //設置操做類型
5     e.AcceptedOperation = DataPackageOperation.Copy;
6  
7     //設置提示文字
8     e.DragUIOverride.Caption = "拖放此處便可添加文件 o(^▽^)o";
9 }

Drop事件中咱們來處理拖動完成時的邏輯,以下:

 1 private async void VcBorder_Drop(object sender, DragEventArgs e)
 2 {
 3     /*
 4         接收端能夠根據e.DataView.Contains(StandardDataFormats formats) 來肯定拖動過來的數據中是否包含某種數據類型
 5         若是數據類型不匹配就取的話則會報錯
 6     */
 7     if (e.DataView.Contains(StandardDataFormats.StorageItems))
 8     {
 9         //獲取存儲對象
10         var items = await e.DataView.GetStorageItemsAsync();
11  
12         //諮詢是否接受文件
13         var dialog = new ContentDialog
14         {
15             Title = "提示",
16             Content = new TextBlock {Text = $"從其餘App中拖動來{items.Count}個文件,是否接受?"},
17             IsPrimaryButtonEnabled = true,
18             IsSecondaryButtonEnabled = true,
19             PrimaryButtonText = "Ok",
20             SecondaryButtonText = "Cancel"
21         };
22         dialog.PrimaryButtonClick += async (s, a) =>
23         {
24             //開始接受文件 並添加到ImgList中 ,或者也能夠作其餘操做,例如保存文件到App中
25             //過濾下文件,只取jpg文件
26             foreach (var item in items.OfType<StorageFile>()
27                 .Where(i => i.FileType.Equals(".jpg")).ToList())
28             {
29                 var bitmapImage = new BitmapImage();
30                 await bitmapImage.SetSourceAsync(await item.OpenAsync(FileAccessMode.Read));
31                 ImgList.Items?.Add(new Image {Source = bitmapImage});
32             }
33         };
34         dialog.SecondaryButtonClick += (s, a) => { dialog.Hide(); };
35         await dialog.ShowAsync();
36     }
37  
38     if (e.DataView.Contains(StandardDataFormats.Bitmap))
39     {
40         //獲取bitmap對象
41         var items = await e.DataView.GetBitmapAsync();
42         var bitmap = new BitmapImage();
43         await bitmap.SetSourceAsync(await items.OpenReadAsync());
44         //設置MainGrid背景圖片
45         MainGrid.Background = new ImageBrush {ImageSource = bitmap};
46     }
47 }

有關更多Drop事件&DragOver事件詳細設置請參與文章:UWP/Win10新特性系列—Drag&Drop拖動打開文件

這樣咱們就實現了從一個UWP中拖動元素到其餘App中,例如能夠拖動到文件夾中快速保存圖片,也能夠拖動到outlook中快速插入附件,也能夠拖動圖片到另外一個App中進行操做等。

 

效果圖:

 

推薦一個UWP開發羣:53078485 你們能夠進來一塊兒學習

相關文章
相關標籤/搜索