除了可以使用XXXFilePicker来浏览文件外,其实在UWP APP中,也可以向传统Windows窗口一样,通过拖放的方式来打开文件。

处理过程和WPF的原理差不多,毕竟都是一脉相承,于是,在学习过程完全可以进行知识迁移。如果希望界面上某个可视化对象作为拖放的放置目标,请务必把它的AllowDrop属性设置为true,这是必须完成的,不然被拖动的内容无法放到该元素上。

作为可视化对象的基类,UiElement类为拖放操作提供了支持。

除了前面提到的AllowDrop属性,还包含以下事件:

DragStarting:当开始拖放操作但未正式启动拖放时发生,在此事件中,你可以设置要传递的数据,如果后悔了,不想拖放了,在此事件中可以取消拖放操作。注意,此事件是针对当前对象而言的,即当前对象自身发起拖放操作时发生。要在当前对象上启动一个新的拖放操作,请调用当前对象的StartDragAsync方法。这些成员都是在UIElement上定义的,所以它的子类都会继承。

DragEnter、DragOver和DragLeave:注意,这三个事件是被拖动的对象经过当前对象时发生的。当被拖动的对象进入当前对象的可视区域时会发生DragEnter事件;当被拖动的对象在当前对象上移动时会发生DragOver事件,只要被拖动对象还处理当前对象上方,那么你鼠标或手指只要动一下(坐标有变),DragOver事件也会发生。当被拖动的对象离开当前对象的可视区域时会发生DragLeave事件。整个过程在正常情况下应该为:Enter -> Over -> Leave。不正常情况下就难说了,比如有些质量特别好的鼠标,拖着拖着,光标就不见了。在DragEnter事件中,可以对拖过来的数据进行验证,如果不符合你的口味,可以考虑“退货”。

Drop:当数据被拖到当前对象上,并且放开时发生。在该事件中就应该获取传递进来的数据。如果此时不获取就没机会了,“今生今世若不能结发,来世就是旁人家的了”。

DropCompleted:放置操作完成后会发生该事件。你可以不处理这个事件。但你要注意,在这个事件中你是不能获取传递的数据的,前面发生的Drop事件是获取数据的最后机会,不要错过。

下面给大家弄一个通过拖放来打开图片文件的示例。我就不搞太复杂了,免得有人说我装H。

先看界面,重点是看开启拖放支持。

        <Border HorizontalAlignment="Center" VerticalAlignment="Center" Name="bd" Background="Blue" Padding="50,25" AllowDrop="True" DragEnter="OnDragenter" DragLeave="OnDragleave" Drop="OnDrop">
<TextBlock Name="tb" FontSize="28" Foreground="White" Text="请把文件拖至此处"/>
</Border>

你要看的重点是:1、设置AllowDrop属性为True,记住,这一步必须,不然后面就不能把文件拖到这个Border上了;2、处理DragEnter事件,当文件被拖进来时验证一下被拖动的是不是文件;处理DragLeave事件,这个没什么事干,主要是在拖放离开Border后,恢复一下Border的“容貌”而已;处理Drop事件,当释放时获取文件,并显示图片。

具体代码如下:

        private async void OnDragenter(object sender, DragEventArgs e)
{
// 获取Deferral是必须,稍后要用它来向系统报告操作完成
var deferral = e.GetDeferral();
DataPackageView dataview = e.DataView;
// 验证数据类型,如果不是文件,就没戏了
if (dataview.Contains(StandardDataFormats.StorageItems))
{
// 取出被拖进来的文件列表
// 因为用户可能觉得好玩
// 一次性拖一大堆文件或目录进来
var items = await dataview.GetStorageItemsAsync();
if (items.Count > )
{
IStorageItem item = items[];
// 这里只关心文件,如果拖的是目录,那就不玩了
if (item.IsOfType(StorageItemTypes.File))
{
// 设置一个有效的拖放操作,只要不是None就行
// 其他值都无所谓,主要区别是拖放时的光标显示不同
// 但后面我会把光标隐藏,以免影响视线
e.AcceptedOperation = DataPackageOperation.Link;
StorageFile file = (StorageFile)item;
// 得到文件预览图
var t = await file.GetScaledImageAsThumbnailAsync(Windows.Storage.FileProperties.ThumbnailMode.SingleItem, );
BitmapImage bmp = new BitmapImage();
bmp.DecodePixelWidth = ;
bmp.SetSource(t);
// 设置拖动过程中显示的图标
e.DragUIOverride.SetContentFromBitmapImage(bmp);
// Caption属性表示在拖动时显示的提示文本
// 想看效果的话,就把下面这行代码取消注释
//e.DragUIOverride.Caption = file.Name;
// 不显示提示文本
// 所以,如果你想看上面的Caption值,请把
// IsCaptionVisible也改为true
e.DragUIOverride.IsCaptionVisible = false;
// 干脆连那个指针符号也隐藏了吧
e.DragUIOverride.IsGlyphVisible = false;
}
else
{
// 不是文件数据,就设置为None,无操作
e.AcceptedOperation = DataPackageOperation.None;
}
}
}
else
{
e.AcceptedOperation = DataPackageOperation.None;
}
VisualStateManager.GoToState(this, "DragIn", false);
// 告诉系统,我干完活了
deferral.Complete();
}         private void OnDragleave(object sender, DragEventArgs e)
        {
            var d = e.GetDeferral();
            VisualStateManager.GoToState(this, "Generic", false);
            d.Complete();
        } private async void OnDrop(object sender, DragEventArgs e)
{
// 记得获取Deferral对象
var def = e.GetDeferral();
DataPackageView data = e.DataView;
// 还是再验证一下吧,防止意外
if (data.Contains(StandardDataFormats.StorageItems))
{
var storageItems = await data.GetStorageItemsAsync();
if (storageItems.Count > )
{
IStorageItem item = storageItems[];
if (item.IsOfType(StorageItemTypes.File))
{
StorageFile file = item as StorageFile;
// 生成内存图像
using (var inStream = await file.OpenReadAsync())
{
BitmapImage bmp = new BitmapImage();
bmp.DecodePixelWidth = ;
bmp.SetSource(inStream);
img.Source = bmp; //显示图像
}
}
}
}
VisualStateManager.GoToState(this, "Generic", false);
// 报告操作系统,处理完成
def.Complete();
}

代码虽然比较long,但其实没什么,因为DragEnter和Drop事件的代码相近,但,DragEnter事件重点是验证数据,而Drop事件代码重点是获取数据。在该事件中你必须获取数据,否则Drop完之后,整个拖放操作已经完成,你不再有机会获取了。

这里我必须说明一个非常严重的问题,本来不是很严重的,就是某些人粗心大意,倒弄出问题了。

不少人在使用拖放中出现:应用程序运行后,第一次拖放操作可以顺利完成。但之后就不能拖放了。于是就反馈说有Bug。Bug你个头啊,为什么人家其他程序又能正常使用?

你仔细看我的代码,在处理事件时,要先调用GetDeferral方法获取一个对象,在代码完成之后,调用这个对象的Complete方法,告知系统操作完成。这个Deferral我以前说过,Runtime App中常出现的,它大概是一个代理对象,来延缓某些线程的操作,直到Complete方法调用才释放。为什么说是代理对象,因为Runtime API类似于COM组件,实际上它是本地代码,只是为了和.net的风格统一,就封装为类似托管API的形式。

            var d = e.GetDeferral();
……
d.Complete();

记好了,以后遇到问题别瞎胡扯,多从自己身上找问题。毛主席常教导我们,多想出智慧,多做自我批评。

运行应用程序,然后打开文件管理器,随便找个图像文件拖到窗口上的Border对象上,就可以打开文件了。

得到文件后,可以显示图片了。

好啦,快要刮台风了,所以牛逼就不多吹了,今天就吹到这里吧。

示例代码下载:http://files.cnblogs.com/files/tcjiaan/dragOpenFileSmp.zip

【Win10应用开发】通过拖放来打开文件的更多相关文章

  1. C#实现文件拖放并打开文件(使用ListBox)

    1.C#实现文件拖放并打开文件 (http://www.cnblogs.com/GaoHuhu/archive/2012/10/10/2717954.html)

  2. win10下EditPlus不能拖拽打开文件

    今天找到篇blog,终于把win10下EditPlus不能拖拽打开文件的问题解决了:) 记录下备忘.之前通过注册表的方式添加到右键菜单,当时设置了EditPlus以管理员身份运行: 解决办法=> ...

  3. 【Win10 应用开发】集成文件打开选择器

    有朋友给老周提出建议:老周,能不能在写博客时讲一下有深度的小故事?技术文章谁不会写.讲一下对人生有启发性的故事会更好. 哎呀,这要求真是越来越高了.好吧,尽量吧,如果有小故事的话,老周在就每次写博客时 ...

  4. UWP/Win10新特性系列—Drag&Drop 拖动打开文件

    在Win10 App开发中,微软新增了系统PC文件与UWP 之间的文件拖拽行为,它支持将系统磁盘上的文件以拖拽的形式拖入App中并处理,在前不久的微软build 2015开发者大会上微软展示的UWP版 ...

  5. cfile fopen fopen_s win10下打开文件失败

    vc程序在win10下面使用fopen 打开文件失败,在网上查 了下是因为UAC权限的问题如下: 由于windows vista win7 win8 win 10 添加了UAC权限,所以会导致 在系统 ...

  6. win10 只要打开文件对话框就卡死解决方法

    我电脑的问题是:win10系统,只要打开 文件对话框就卡死,假死,cpu100% 一直没有解决,但是只要把缩略图关了,就ok. 但是又想要留着缩略图,还是得显示,于是乎一直在找解决办法. 此方法好像可 ...

  7. 跟我一起玩Win32开发(19):浏览和打开文件

    在应用程序中,我们很经常要实现的功能,是Open文件或保存文件对话框,让用户来选择一个或N个文件.本文我将介绍两种思路,第一种方法较为复杂,第二种方法较为简单. 方法一:老规矩 这是一种传统方法,使用 ...

  8. ( 转转)Android初级开发第九讲--Intent最全用法(打开文件跳转页面等)

    大家好,今天跟大家谈谈Intent的用法. Intent在安卓中主要用于打开另外一个页面,这个页面可能是一个activity也可能是一个应用,也可能是     其它…… 且看下面介绍,总结摘抄网友一些 ...

  9. 微信小程序云开发-云存储-上传、下载、打开文件文件(word/excel/ppt/pdf)一步到位

    一.wxml文件 <!-- 上传.下载.打开文件一步执行 --> <view class="handle"> <button bindtap=&quo ...

随机推荐

  1. mac安装java8

    http://stackoverflow.com/questions/24342886/how-to-install-java-8-on-mac brew tap caskroom/cask brew ...

  2. spring源码解析——spring源码导入eclipse

    一.前言     众所周知,spring的强大之处.几乎所有的企业级开发中,都使用了spring了.在日常的开发中,我们是否只知道spring的配置,以及简单的使用场景.对其实现的代码没有进行深入的了 ...

  3. var a=b=c=1; 和 var a=1, b=2, c=3; 的区别。

    function test(){ var a=b=c=1; var a=1, b=2,c=3; } 1中b\c 为全局变量, a为私量 2中a\b\c为私量

  4. CI框架代码运行最详细的流程

    最近在学习CI(3.1.0-dev)框架源码,一边看源码,一边在github上面写中文注释,https://github.com/pandancode/CI-note,有兴趣的同学可以看看. inde ...

  5. 我的前端故事----Ajax方式和jsonp的实现区别

    很久没有更新博客了,毕业2个月了,这段时间一直在忙于工作,一直没有时间更新,最近做的活动突然发现之前的经验居然忘记了...索性想想还是重新开始用博客记录平日里的工作经验吧,吐槽就到这里了,这篇记录的是 ...

  6. 如何设置GridView中某个字段显示数据的一部分?

    后台方法: /// <summary> /// 截取字符串 /// </summary> /// <param name="str">要截取的字 ...

  7. eclipse的SVN插件去除无效的文件

  8. 通读AFN②--AFN的上传和下载功能分析、SessionTask及相应的session代理方法的使用细节

    这一部分主要研究AFN的上传和下载功能,中间涉及到各种NSURLSessionTask的一些创建的解析和HTTPSessionManager对RESTful风格的web应用的支持,同时会穿插一点NSU ...

  9. 【Beta】Daily Scrum Meeting第五次

    1.任务进度 学号 已完成 接下去要做 502 登陆时将返回的个人信息更新到本地数据库 发布任务到服务器 509 给所有api添加注释 添加及修改职工信息并同步到服务器 517 将提交报课移到报课表界 ...

  10. Android Intent Flags

    Intent,顾名思义,即意图,通常用它来启动一个应用程序组件( Activity, Service, 或者 BroadCast Receiver ).在启动一个新的 Activity 时,可以通过给 ...