zoukankan      html  css  js  c++  java
  • Win10/UWP新特性—Drag&Drop 拖出元素到其他App

        在以前的文章中,写过微软新特性Drag&Drop,当时可能由于处于Win10预览版,使用的VS也是预览版,只实现了从桌面拖拽文件到UWP App中,没能实现从UWP拖拽元素到Desktop App & UWP App中。昨天重新研究了Win10 拖拽这一块,发现以前没能实现的功能,在正式版的环境下都可以实现了,做个笔记以防日后忘记。

        在UWP中,想要拖动元素到Desktop或者另一个UWP App中,除了设置元素的CanDrag="True"我们要使用元素的DragStarting事件,CanDrag属性设置元素能被拖动,DragStarting事件中我们便可以为拖动准备数据,改变拖动时的UI等一些操作。

        我们依然使用上篇Drag&Drop文章中例子,在底部新增一个Img元素,设置如下:

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

    我们要用到事件的DragStartingEventArgs参数,在该参数中我们可以为拖动准备拖动的数据,更改UI设置,其中有几个重要的属性和方法:

    <!--/* 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事件中处理拖动如下:

    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(@"AssetsI Am 1%.jpg");
        args.Data.SetBitmap(RandomAccessStreamReference.CreateFromFile(sf));
    }

    上面我们一共设置两种数据,第一种是通过args.Data.SetStorageItems()方法将指定文件夹下的图片赋值到拖动Data上,第二种我们通过args.Data.SetBitmap()方法设置了一个图片到Data的BitMap中。

    使用时,我们在拖动元素到另一个App(接收者)中时,就要根据上面具体设置的数据类型来获取到相应的数据。

    接下来我们创建一个新的UWP App(接收者) ,界面上放置一个ListView,并设置可接受拖动数据,然后订阅相关的拖动事件如下:

    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容器的背景色赋值。

    DragOver事件中,我们可以更改拖动元素到目标范围内时的UI外观,定制如下:

    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 大家可以进来一起学习

  • 相关阅读:
    Annotation Type ManyToMany->>>>>Oracle
    windows 控制台默认为UTF-8显示的方法
    springboot读取配置文件
    Spring Boot配置文件放在jar外部
    Vue自定义过滤器
    vue中limitBy,filterBy,orderBy的用法
    track-by的使用
    Vue的computed属性
    vue实现百度下拉框
    Cas服务器以及客户端搭建
  • 原文地址:https://www.cnblogs.com/Aran-Wang/p/4816254.html
Copyright © 2011-2022 走看看