除了可以使用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. Android MVP 利用rxjava 避免向Model传入监听方法

    传统的MVP: 1.抽离出View的接口,即ILoginView. 2.抽离Model的接口,即ILoginModel. 3.抽离Presenter的接口,即ILoginPresenter. 4.实现 ...

  2. 0_MVC+EF+Autofac(dbfirst)轻型项目框架_基本框架

    前言 原来一直使用他人的开源项目框架,异常的定位会很麻烦,甚至不知道这个异常来自我的代码还是这个框架本身.他人的框架有一定的制约性,也有可能是我对那些框架并没深入了解,因为这些开源框架在网上也很难找到 ...

  3. linux shell输出带颜色文本

    echo -e "\033[33;31m Color Text" - red echo -e "\033[33;32m Color Text" - green ...

  4. Android 无标题 全屏设置

    标题栏和状态栏 Android程序默认情况下是包含状态栏和标题栏的. 在Eclipse中新建一个Android程序,运行后显示如下: 图中标出了状态栏(显示时间.电池电量.网络等)和标题栏(显示应用的 ...

  5. 扩展BindingList,防止增加、删除项时自动更新界面而不出现“跨线程操作界面控件 corss thread operation”异常

    在做界面程序时,常常需要一些数据类,界面元素通过绑定等方式显示出数据,然而由于UI线程不是线程安全的,一般都需要通过Invoke等方式来调用界面控件.但对于数据绑定bindingList而言,没法响应 ...

  6. ubuntu16.04 install flash

    今天安装了一下flash,发现不同版本的Ubuntu复制的位置不同,此处介绍Ubuntu16.04的安装方式 1.首先下载flash,下载tar.gz的 2.解压缩到当前目录 3,打开terminal ...

  7. Linux Shell 截取字符串

    Linux Shell 截取字符串 shell中截取字符串的方法很多 ${var#*/} ${var##*/} ${var%/*} ${var%%/*} ${var:start:len} ${var: ...

  8. JavaScript固定宽高

    固定高宽:  <script type="text/javascript">         if (/Android (\d+\.\d+)/.test(navigat ...

  9. js中this的用法

    经过近几周的模拟面试题,我查询了一些资料,今天就来说说,在js中this的用法吧.方法有四:第一,用作全局变量,第二,用作表该对象,第三,用作构造函数,第四,用作call和applay

  10. python setup.py 管理

    发布项目遇到了坑……特此记录. How to write setup.py: https://docs.python.org/2/distutils/setupscript.html Setup.py ...