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- ...
随机推荐
- 关于PHP函数time() date() 和 strtotime() 的时区问题
最近项目中有个需求, 要记录新注册用户的次日登录情况, 于是写出了如下代码: $create_time = '用户注册时间'; //格式 Y-m-d H:i:s $time = time(); $la ...
- react参考项目001
https://github.com/chen2009277025/webpack-ant-design-demo https://github.com/cobish/cobish.github.io ...
- redhat openshift 跳转
网址: https://openshift.redhat.com/ OpenShift免费套餐的限制是:最多15PV/s,有3个512MB内存的应用,月流量在50K以下. 可以绑米,可惜的是,需要代理 ...
- Oracle查询
1.普通查询 select * from 表格 查询所有内容 select 列名,列名 from 表格查询某几列 2.条件查询 select * from 表格 where 条件 条件查询 selec ...
- MySQL主主复制
MySQL5. 主主复制 环境如下: CentOS6.4_64 MySQL5. master1:192.168.10.11 master2:192.168.10.12 1.1 配置 master1 a ...
- python 获取脚本所在目录
平时写python经常会想获得脚本所在的目录,例如有个文件跟脚本文件放在一个相对的目录位置,那就可以通过脚本文件的目录找到对应的文件,即使以后脚本文件移到其他地方,脚本也基本不需要改动(相对于写死目录 ...
- bzoj 3172 单词 ac自动机|后缀数组
题目大意: 给定n个字符串连成了一篇文章,问每个字符串在这篇文章中出现的次数,可重复覆盖 这里ac自动机和后缀数组都可以做 当然后缀数组很容易就解决,但是相对时间消耗高 这里就只讲ac自动机了 将每个 ...
- 阿里云服务器被挖矿minerd入侵的解决办法
上周末,更新易云盘的时候,发现阿里云服务器CPU很高,执行 top 一看,有个进程minerd尽然占用了90%多的CPU, 赶紧百度一下,查到几篇文章都有人遇到同样问题 Hu_Wen遇到的和我最相似, ...
- Httpclient请求数据(post)
public static String loginCheck_POST_HttpClient(String name,String pass,String url){ String result = ...
- flexbox实现不等宽不等高的瀑布流布局
第一次做不等宽不等高的瀑布流布局,刚开始企图用ccs3的column属性+flexbox来实现,瞎捣鼓半天都没有能弄好, 弱鸡哭晕在厕所(┬_┬),气的午饭都没有吃. 后来逼着自己冷静下来,又捣鼓了1 ...