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(@"Assets\I 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 大家可以进来一起学习

时间: 2024-12-18 18:05:59

Win10/UWP新特性—Drag&Drop 拖出元素到其他App的相关文章

Win10/UWP新特性—SharedStorageAccessManager 共享文件

首先先给大家推荐一个UWP/Win10开发者群:53078485  里面有很多大婶,还有很多学习资源,欢迎大家来一起讨论Win10开发! 在UWP开发中,微软提供了一个新的特性叫做SharedStorageAccessManager,它允许我们的App根据指定的文件生成一个FileToken来共享此文件,其他App可以使用SharedStorageAccessManager. RedeemTokenForFileAsync(fileToken);方法根据FileToken来获取到共享的文件.这样

Win10/UWP新特性系列—Launcher实现应用间的通信

UWP中,微软为Windows.System.Launcher启动器新增了很多的功能,以前只能启动App,打开指定扩展名文件,对uri协议的解析,以及当启动的应用没有安装时则会提示前往商店下载等. 如今,微软丰富了Launcher的功能,使用新的Launcher我们可以在App中实现调用文件资源管理器.App-To-App Server(应用对应用服务),Background Task Server App(后台任务处理服务App)还有设置页面调用. 一:Launcher.LaunchFolde

Win10/UWP新特性系列—电池报告

UWP中,新增了当节电模式开启时,App能获取到通知的API,通过响应电源条件的更改,比如咨询用户是否使用黑色背景等来帮助延长电池使用时间. 通过Windows.Devices.Power命名空间中的电池API,你可以了解到正在运行的设备所有的电池详细信息. 通过创建Battery对象来表示单个电池控制器或聚合的所有电池控制器,然后使用GetReport方法返回BatteryReport对象,该对象可指示响应电池的充电.容量和状态. 需要用到的资源: Battery:提供该设备的电池控制器信息类

Win10/UWP新特性系列-GetPublisherCacheFolder

微软Windows Runtime App拥有很强的安全模型来防止不同App之间的数据获取和共享,也就是我们所说的"沙盒机制",每个App都运行在Windows沙盒中,App之间的数据是不会被别的App获取到的. 在UWP中,微软新增了GetPublisherCacheFolder —— 共享存储文件夹的机制,这个获取的共享存储文件夹并不是说打破了原有的"沙盒机制",而是指,同一个软件开发商发布的App之间,是允许访问一个共享的文件夹以及里面的内容.例如,多个应用程

Win10/UWP新特性系列—使用打印机

微软在Win10时代终于完成的设备系统的大统一,"56个民族,56支花……"(⊙o⊙)…,既然统一了,那么也就意味着API也统一了,所以在UWP中,我们就可以使用统一的打印API来为设备(包括移动设备)添加基于XAML的App打印功能.使用Windows.Graphics.Printing和Windows.UI.Xaml.Printing命名空间,就可以很方便的将打印功能添加到我们的应用中. 下面是个例子,我们需要打印一个购物清单,前台代码如下: 1 <Page.Resource

Atitit。D&amp;D drag&amp;drop拖拽功能c#.net java swing的对比与实现总结

Atitit.D&D drag&drop拖拽功能c#.net java swing的对比与实现总结 1. 实现一个D&D操作一般包括三个步骤: 1 2. .net黑头的拖曳机制.必须有DragEnter事件(单独写DragDrop事件是不会具有拖拽功能的) 2 3. ---java黑头的拖曳..必须有DragEnter事件(单独写 Drop事件是不会具有拖拽功能的) 2 4. 代码 3 5. 参考 5 1. 实现一个D&D操作一般包括三个步骤: 首先实现一个拖拽源,这个拖拽

atitit.D&amp;D drag&amp;drop拖拽文件到界面功能 html5 web 跟个java swing c#.net c++ 的总结

atitit.D&D drag&drop拖拽文件到界面功能 html5 web 跟个java swing c#.net c++ 的总结 1. DND的操作流程 1 2. Html5 注解事件 document.dragover >>preventDefault 1 3. 代码(js) 1 4. C++ 实现拖曳 2 5. QT拖拽功能简介 - pcsuite的专栏 - 博客频道 - CSDN.NET.htm 2 1. DND的操作流程 Dragenter 事件::更改提示的颜色

atitit。win7 win8 win9 win10 win11 新特性总结与战略规划

atitit.win7 win8 win9 win10  win11 新特性总结与战略规划 1. win7 1 1.1. 发布时间 2009年10月22日 1 1.2. 稳定性大幅提升,很少蓝屏死机 1 1.3. 很少损坏不能启动(只有一次,2年,多机) 1 1.4. PC也可以触摸 1 2. win8 新特性 2 2.1. 2012年2月29日 2 2.2. Metro界面跨平台(移动平台,) 2 2.3. 本文导航 2 2.4. U盘上也可运行 2 3. win9 新特性 3 3.1. wi

SQL Server 2016新特性:DROP IF EXISTS

原文:SQL Server 2016新特性:DROP IF EXISTS ?? 在我们写T-SQL要删除某个对象(表.存储过程等)时,一般会习惯先用IF语句判断该对象是否存在,然后DROP,比如: 旧版本: IF OBJECT_ID('dbo.PERSON','U') IS NOT NULL DROP TABLE PERSON IF EXISTS (SELECT * FROM sys.objects where name = 'PERSON') DROP TABLE PERSON SQL Ser