UWP/Win10新特性系列—Drag&Drop 拖动打开文件
在Win10 App开发中,微软新增了系统PC文件与UWP 之间的文件拖拽行为,它支持将系统磁盘上的文件以拖拽的形式拖入App中并处理,在前不久的微软build 2015开发者大会上微软展示的UWP版微信的拖拽文件就是使用的这个功能,接下来,我们一起看看该功能是怎么实现的。
首先我们要介绍的是DragEventArgs这个类,是在拖拽中为我们提供数据和UI样式定制的,在拖拽事件中,事件参数对象就是该类型,这个类在Win10中增加了一个新的接口的继承->IDragEventArgs2接口,该接口中提供如下新的成员属性:
internal interface IDragEventArgs2
{
DataPackageOperation AcceptedOperation { get; set; }
DataPackageView DataView { get; }
DragUIOverride DragUIOverride { get; }
DragDropModifiers Modifiers { get; } DragOperationDeferral GetDeferral();
}
其中有三个比较重要的:
- AcceptedOperation:这个是获取或设置指定拖动事件发起方可执行哪些操作,值是DataPackageOperation枚举类型。可以制定四种操作类型(None,Move,Copy,Link),指定不同类型时在拖拽时会产生不同的图标样式。
- DataPackageView:这个属性是用来获取拖拽进来的对象的数据的,根据它可以拿到拖拽对象。
- DragUIOverride:这个是用来自定义拖拽时的UI外观的,可以改变拖拽时的图标、提示语、是否显示图标和提示语等。
要想让元素接受拖拽对象到它自己本身,我们要设置元素的AllowDrop属性为True,拖拽会触发四种事件:DragEnter(进入接受拖拽的范围)、DragOver(处于接受拖拽范围)、Drop(松开鼠标)、DragLeave(离开接受拖拽的范围),整体的拖拽流程是这样的:
而我们需要订阅该元素的Drop、DragOver两个事件,DragOver事件会在拖拽对象到该元素时一直被触发,而当鼠标松开拖拽时会触发Drop事件。
接下来,我们演示下从系统磁盘文件夹拖拽一些vcf联系人到我们的App中。
界面上放置三个区域:接受拖拽区、文件显示区、拖拽删除区
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="8*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions> <!--接受拖拽的区域 Start-->
<Border AllowDrop="True"
Drop="VcBorder_Drop"
DragOver="VcBorder_DragOver"
Background="{ThemeResource ToolTipForegroundThemeBrush}" >
<TextBlock Text="请尝试拖动vcf名片到这里" RequestedTheme="Dark" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<!--接受拖拽的区域 End--> <!--拖拽过来的文件显示区 Start-->
<Grid Grid.Row="1" >
<ListView x:Name="VcList" CanDragItems="True" DragItemsStarting="VcList_DragItemsStarting"
ItemsSource="{x:Bind VCards }" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:LinkManModel">
<Grid Margin="0,8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<Grid>
<Image Source="Assets/I Am 1%.jpg" />
<Image Source="{x:Bind Img}" />
</Grid>
<Grid Margin="12,0" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock>
<Run Text="姓名:"/>
<Run Text="{x:Bind Name}"/>
</TextBlock>
<TextBlock Grid.Row="1">
<Run Text="Phone:"/>
<Run Text="{x:Bind Phone}"/>
</TextBlock>
<TextBlock Grid.Row="2">
<Run Text="Email:"/>
<Run Text="{x:Bind Email}"/>
</TextBlock>
</Grid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
<!--拖拽过来的文件显示区 End--> <!--拖拽删除区 Start-->
<Border Grid.Row="2" x:Name="DelBorder"
AllowDrop="True"
Drop="DelBorder_Drop"
DragOver="DelBorder_DragOver"
Background="{ThemeResource ToolTipForegroundThemeBrush}">
<TextBlock Text="请拖动名片到这里来删除" RequestedTheme="Dark" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<!--拖拽删除区 End-->
</Grid>
后台代码:
public sealed partial class MainPage : Page
{ public ObservableCollection<LinkManModel> VCards = new ObservableCollection<LinkManModel>(); public MainPage()
{
this.InitializeComponent();
} /// <summary>
/// 拖拽完成
/// </summary>
private async void VcBorder_Drop(object sender, DragEventArgs e)
{
Debug.WriteLine("[Info] Drop"); if (e.DataView.Contains(StandardDataFormats.StorageItems))
{
Debug.WriteLine("[Info] DataView Contains StorageItems");
var items = await e.DataView.GetStorageItemsAsync(); //文件过滤 只取vcf文件 PS:如果拖过来的是文件夹 则需要对文件夹处理 取出文件夹文件
items = items.OfType<StorageFile>()
.Where(s => s.FileType.Equals(".vcf")).ToList() as IReadOnlyList<IStorageItem>;
if (items != null && items.Any())
{
//添加VCard
await AddVCard(items);
}
}
} /// <summary>
/// 添加VCard
/// </summary>
/// <param name="items"></param>
/// <returns></returns>
private async Task AddVCard(IReadOnlyList<IStorageItem> items)
{
foreach (var item in items)
{
#region 图片的处理
//var storageFile = item as StorageFile;
//var bitmapImage = new BitmapImage();
//await bitmapImage.SetSourceAsync(await storageFile.OpenAsync(FileAccessMode.Read));
#endregion var linkMan = new LinkManModel();
var storageFile = item as StorageFile;
var stream = await storageFile.OpenStreamForReadAsync();
using (StreamReader reader = new StreamReader(stream))
{
var str = reader.ReadToEnd();
var vcard = VCard.Parse(str);
var info = vcard.Properties;
linkMan.Name = info.FirstOrDefault(s => s.Name == "FN") == null ? null : info.FirstOrDefault(s => s.Name == "FN").EncodedValue;
linkMan.Phone = info.FirstOrDefault(s => s.Name == "TEL") == null ? null : info.FirstOrDefault(s => s.Name == "TEL").EncodedValue;
linkMan.Email = info.FirstOrDefault(s => s.Name == "EMAIL") == null ? null : info.FirstOrDefault(s => s.Name == "EMAIL").EncodedValue;
var photoStr = info.FirstOrDefault(s => s.Name == "PHOTO") == null ? null : info.FirstOrDefault(s => s.Name == "PHOTO").EncodedValue;
if (photoStr != null)
linkMan.Img = await convertToImage(photoStr); }
if (linkMan != null)
{
VCards.Add(linkMan);
}
}
} /// <summary>
/// base64 To BitmapImage
/// </summary>
private async static Task<BitmapImage> convertToImage(string strimage)
{
try
{
byte[] bitmapArray;
bitmapArray = Convert.FromBase64String(strimage);
MemoryStream ms = new MemoryStream(bitmapArray);
InMemoryRandomAccessStream randomAccessStream = new InMemoryRandomAccessStream();
//将randomAccessStream 转成 IOutputStream
var outputstream = randomAccessStream.GetOutputStreamAt();
//实例化一个DataWriter
DataWriter datawriter = new DataWriter(outputstream);
//将Byte数组数据写进OutputStream
datawriter.WriteBytes(bitmapArray);
//在缓冲区提交数据到一个存储区
await datawriter.StoreAsync(); //将InMemoryRandomAccessStream给位图
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(randomAccessStream); return bitmapImage;
}
catch
{
return null;
}
} /// <summary>
/// 进入到接受拖拽区
/// </summary>
private void VcBorder_DragOver(object sender, DragEventArgs e)
{
Debug.WriteLine("[Info] DragOver");
//设置操作类型
e.AcceptedOperation = DataPackageOperation.Copy; //设置提示文字
e.DragUIOverride.Caption = "拖放此处即可添加文件 o(^▽^)o"; ////是否显示拖放时的文字 默认为true
//e.DragUIOverride.IsCaptionVisible = true; ////是否显示文件图标,默认为true
//e.DragUIOverride.IsContentVisible = true; ////Caption 前面的图标是否显示。默认为 true
//e.DragUIOverride.IsGlyphVisible = true; ////自定义文件图标,可以设置一个图标
//e.DragUIOverride.SetContentFromBitmapImage(new BitmapImage(new Uri("ms-appx:///Assets/copy.jpg")));
} /// <summary>
/// 要删除的项
/// </summary>
LinkManModel DelItem; /// <summary>
/// 开始拖拽Item 以准备删除
/// </summary>
private void VcList_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
{
DelItem = e.Items.FirstOrDefault() as LinkManModel;
} /// <summary>
/// 拖拽删除完成
/// </summary>
private void DelBorder_Drop(object sender, DragEventArgs e)
{
VCards.Remove(DelItem);
} /// <summary>
/// 进入拖拽删除区
/// </summary>
private void DelBorder_DragOver(object sender, DragEventArgs e)
{
//设置操作类型
e.AcceptedOperation = DataPackageOperation.Move;
e.DragUIOverride.Caption = "删除";
e.DragUIOverride.IsContentVisible = false;
} } public class LinkManModel
{
public string Name { get; set; } public string Email { get; set; } private string _Phone;
public string Phone { get { return string.IsNullOrEmpty(_Phone)? null : Regex.Replace(_Phone, @"(?im)(\d{3})(\d{4})(\d{4})", "$1***$3"); } set { _Phone = value; } }
public BitmapImage Img { get; set; }
}
效果:
推荐一个UWP开发群:53078485 大家可以进来一起学习
UWP/Win10新特性系列—Drag&Drop 拖动打开文件的更多相关文章
- UWP/Win10新特性系列—App Service
Win10中,新增了一个很实用的新特性叫做App Service,App Service允许App不在前台运行的情况下提供出一个或多个对外服务供其他App使用,这看起来就好像Web开发中的Web Ap ...
- UWP/Win10新特性系列—UserConsentVerifier
在UWP开发中,微软提供了新的用户许可验证方式-指纹(生物识别).Pin.密码验证.在爆料的新型Win10 Mobile移动设备中,会增加虹膜识别等先进的用户身份识别技术,微软现在统一了身份验证的AP ...
- Java8新特性系列-默认方法
Java8 Interface Default and Static Methods 原文连接:Java8新特性系列-默认方法 – 微爱博客 在 Java 8 之前,接口只能有公共抽象方法. 如果不强 ...
- Java8新特性系列-Lambda
转载自:Java8新特性系列-Lambda – 微爱博客 Lambda Expressions in Java 8 Lambda 表达式是 Java 8 最流行的特性.它们将函数式编程概念引入 Jav ...
- atitit.D&D drag&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 注 ...
- UWP入门(十一)--使用选取器打开文件和文件夹
原文:UWP入门(十一)--使用选取器打开文件和文件夹 很漂亮的功能,很有趣 重要的 API FileOpenPicker FolderPicker StorageFile 通过让用户与选取器交互来访 ...
- 【重点突破】——Drag&Drop拖动与释放
一.引言 在学习HTML5新特性的时候,学到了Drag&Drop这两种拖放API,这里根据拖动的是“源对象”还是“目标对象”做两个小练习,主要是为了理解与应用HTML5为拖放行为提供的7个事件 ...
- ArcGIS Server 10.1新特性系列---动态图层
ArcGIS Server 10.1新特性里面有几个新功能是非常棒的,其中有一个就是动态图层.动态图层不是一种新发明的图层,而是说在arcgis server的web应用中可以动态的配置其渲染和内容功 ...
- 【Servlet3.0新特性】第03节_文件上传
这是一个Web Project 首先是web.xml <?xml version="1.0" encoding="UTF-8"?> <web- ...
随机推荐
- CSS3让一段文字多余的用省略号表示,当鼠标移动上去的时候显示全部文字
<style type="text/css"> div { width:100px; overflow:hidden; white-space:nowrap; text ...
- 关于RequireJS与AngularJS的集成文档
为什么要整合RequireJS RequireJS是一个Javascript 文件和模块框架,通过模块的方式来配置js文件之间的依赖关系,遵守的是CommonJS的AMD标准. 在开发的时候则无需关注 ...
- PV与并发之间换算的算法换算公式
并发连接数 = PV / 统计时间 * 页面衍生连接次数 * http响应时间 * 因数 / web服务器数量 PV = 并发连接数 * 统计时间 * web服务器数量/ 页面衍生连接次数 / htt ...
- 山锅(samgor)的博客 2014
搞移动端的前端开发已经3年,悄悄地从一个前端小白变成老油条. 项目已经做了好几个,最近发现技术的提升貌似停滞不前.说很菜吧,知道的还是不少.说精通吧,自我感觉还算不上. 认真的考虑下这个问题,觉得技术 ...
- 书旗小说app点评
书旗小说这个手机软件用了好久了,大一的时候就开始用,业余无聊时间可以看一看网络小说打发一下时间. 书旗免费小说是一款内容以免费小说书旗网为基础的在线阅读器,除了拥有传统阅读器的书籍同步阅读.全自动书签 ...
- App Store最新审核标准,中文版
App store最新审核标准(2015.3)公布 1. 条款和条件 1.1 为App Store开发程序,开发者必须遵守 Program License Agreement (PLA).人机交互指南 ...
- OC基础--类的本质
类的本质: 类的本质其实也是一个对象(类对象),只要有了类对象, 将来就可以通过类对象来创建实例对象 程序中第一次使用该类的时候被创建,在整个程序中只有一份.此后每次使用都是这个类对象,它在程序运行时 ...
- 节点操作js jQuery
append() - 在被选元素的结尾插入内容 prepend() - 在被选元素的开头插入内容 after() - 在被选元素之后插入内容 before() - 在被选元素之前插入内容 functi ...
- HTML5资料
1 Canvas教程 <canvas>是一个新的用于通过脚本(通常是JavaScript)绘图的HTML元素.例如,他可以用于绘图.制作图片的组合或者简单的动画(当然并不那么简单).It ...
- [小菜随笔]关于monkey报错日志分析
今天小菜在一个测试群内看到群友发出一个monkey的报错信息,其实是一个很简单的报错 个人觉得monkey虽然操作起来比较简易,但其实查看日志分析日志也是很重要的环节,如果对错误分析不够详细,就容易误 ...