zoukankan      html  css  js  c++  java
  • UWP/Win10新特性系列—Drag&Drop 拖动打开文件

       

      在Win10 App开发中,微软新增了系统PC文件与UWP 之间的文件拖拽行为,它支持将系统磁盘上的文件以拖拽的形式拖入App中并处理,在前不久的微软build 2015开发者大会上微软展示的UWP版微信的拖拽文件就是使用的这个功能,接下来,我们一起看看该功能是怎么实现的。

        首先我们要介绍的是DragEventArgs这个类,是在拖拽中为我们提供数据和UI样式定制的,在拖拽事件中,事件参数对象就是该类型,这个类在Win10中增加了一个新的接口的继承->IDragEventArgs2接口,该接口中提供如下新的成员属性:

    1 internal interface IDragEventArgs2
    2  {
    3      DataPackageOperation AcceptedOperation { get; set; }
    4      DataPackageView DataView { get; }
    5      DragUIOverride DragUIOverride { get; }
    6      DragDropModifiers Modifiers { get; }
    7  
    8      DragOperationDeferral GetDeferral();
    9  }

    其中有三个比较重要的:

    • AcceptedOperation:这个是获取或设置指定拖动事件发起方可执行哪些操作,值是DataPackageOperation枚举类型。可以制定四种操作类型(None,Move,Copy,Link),指定不同类型时在拖拽时会产生不同的图标样式。
    • DataPackageView:这个属性是用来获取拖拽进来的对象的数据的,根据它可以拿到拖拽对象。
    • DragUIOverride:这个是用来自定义拖拽时的UI外观的,可以改变拖拽时的图标、提示语、是否显示图标和提示语等。

    要想让元素接受拖拽对象到它自己本身,我们要设置元素的AllowDrop属性为True,拖拽会触发四种事件:DragEnter(进入接受拖拽的范围)、DragOver(处于接受拖拽范围)、Drop(松开鼠标)、DragLeave(离开接受拖拽的范围),整体的拖拽流程是这样的:

    而我们需要订阅该元素的Drop、DragOver两个事件,DragOver事件会在拖拽对象到该元素时一直被触发,而当鼠标松开拖拽时会触发Drop事件。

    接下来,我们演示下从系统磁盘文件夹拖拽一些vcf联系人到我们的App中。

    界面上放置三个区域:接受拖拽区、文件显示区、拖拽删除区

     1 <Grid  Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >
     2       <Grid.RowDefinitions>
     3           <RowDefinition Height="*"/>
     4           <RowDefinition Height="8*"/>
     5           <RowDefinition Height="*"/>
     6       </Grid.RowDefinitions>
     7  
     8       <!--接受拖拽的区域 Start-->
     9       <Border AllowDrop="True"
    10               Drop="VcBorder_Drop"
    11               DragOver="VcBorder_DragOver"
    12               Background="{ThemeResource ToolTipForegroundThemeBrush}" >
    13           <TextBlock Text="请尝试拖动vcf名片到这里" RequestedTheme="Dark" HorizontalAlignment="Center" VerticalAlignment="Center"  />
    14       </Border>
    15       <!--接受拖拽的区域 End-->
    16  
    17       <!--拖拽过来的文件显示区 Start-->
    18       <Grid Grid.Row="1" >
    19           <ListView x:Name="VcList" CanDragItems="True"  DragItemsStarting="VcList_DragItemsStarting"
    20                     ItemsSource="{x:Bind VCards }" >
    21               <ListView.ItemTemplate>
    22                   <DataTemplate x:DataType="local:LinkManModel">
    23                       <Grid Margin="0,8">
    24                           <Grid.ColumnDefinitions>
    25                               <ColumnDefinition Width="2*"/>
    26                               <ColumnDefinition Width="3*"/>
    27                           </Grid.ColumnDefinitions>
    28                           <Grid>
    29                               <Image Source="Assets/I Am 1%.jpg"  />
    30                               <Image Source="{x:Bind Img}"  />
    31                           </Grid>
    32                           <Grid Margin="12,0" Grid.Column="1">
    33                               <Grid.RowDefinitions>
    34                                   <RowDefinition Height="*"/>
    35                                   <RowDefinition Height="*"/>
    36                                   <RowDefinition Height="*"/>
    37                               </Grid.RowDefinitions>
    38                               <TextBlock>
    39                                     <Run Text="姓名:"/>
    40                                     <Run Text="{x:Bind Name}"/>
    41                               </TextBlock>
    42                               <TextBlock Grid.Row="1">
    43                                     <Run Text="Phone:"/>
    44                                     <Run Text="{x:Bind Phone}"/>
    45                               </TextBlock>
    46                               <TextBlock Grid.Row="2">
    47                                    <Run Text="Email:"/>
    48                                    <Run Text="{x:Bind Email}"/>
    49                               </TextBlock>
    50                           </Grid>
    51                       </Grid>
    52                   </DataTemplate>
    53               </ListView.ItemTemplate>
    54           </ListView>
    55       </Grid>
    56       <!--拖拽过来的文件显示区 End-->
    57  
    58       <!--拖拽删除区 Start-->
    59       <Border Grid.Row="2" x:Name="DelBorder"
    60           AllowDrop="True"
    61               Drop="DelBorder_Drop"
    62               DragOver="DelBorder_DragOver"
    63               Background="{ThemeResource ToolTipForegroundThemeBrush}">
    64           <TextBlock Text="请拖动名片到这里来删除" RequestedTheme="Dark" HorizontalAlignment="Center" VerticalAlignment="Center"  />
    65       </Border>
    66       <!--拖拽删除区 End-->
    67   </Grid>

    后台代码:

      1 public sealed partial class MainPage : Page
      2 {
      3  
      4     public ObservableCollection<LinkManModel> VCards = new ObservableCollection<LinkManModel>();
      5  
      6     public MainPage()
      7     {
      8         this.InitializeComponent();
      9     }
     10  
     11     /// <summary>
     12     /// 拖拽完成
     13     /// </summary>
     14     private async void VcBorder_Drop(object sender, DragEventArgs e)
     15     {
     16         Debug.WriteLine("[Info] Drop");
     17  
     18         if (e.DataView.Contains(StandardDataFormats.StorageItems))
     19         {
     20             Debug.WriteLine("[Info] DataView Contains StorageItems");
     21             var items = await e.DataView.GetStorageItemsAsync();
     22  
     23             //文件过滤 只取vcf文件 PS:如果拖过来的是文件夹 则需要对文件夹处理 取出文件夹文件
     24             items = items.OfType<StorageFile>()
     25                 .Where(s => s.FileType.Equals(".vcf")).ToList() as IReadOnlyList<IStorageItem>;
     26             if (items != null && items.Any())
     27             {
     28                 //添加VCard
     29                 await AddVCard(items);
     30             }
     31         }
     32     }
     33  
     34     /// <summary>
     35     /// 添加VCard
     36     /// </summary>
     37     /// <param name="items"></param>
     38     /// <returns></returns>
     39     private async Task AddVCard(IReadOnlyList<IStorageItem> items)
     40     {
     41         foreach (var item in items)
     42         {
     43             #region 图片的处理
     44             //var storageFile = item as StorageFile;
     45             //var bitmapImage = new BitmapImage();
     46             //await bitmapImage.SetSourceAsync(await storageFile.OpenAsync(FileAccessMode.Read));
     47             #endregion
     48  
     49             var linkMan = new LinkManModel();
     50             var storageFile = item as StorageFile;
     51             var stream = await storageFile.OpenStreamForReadAsync();
     52             using (StreamReader reader = new StreamReader(stream))
     53             {
     54                 var str = reader.ReadToEnd();
     55                 var vcard = VCard.Parse(str);
     56                 var info = vcard.Properties;
     57                 linkMan.Name = info.FirstOrDefault(s => s.Name == "FN") == null ? null : info.FirstOrDefault(s => s.Name == "FN").EncodedValue;
     58                 linkMan.Phone = info.FirstOrDefault(s => s.Name == "TEL") == null ? null : info.FirstOrDefault(s => s.Name == "TEL").EncodedValue;
     59                 linkMan.Email = info.FirstOrDefault(s => s.Name == "EMAIL") == null ? null : info.FirstOrDefault(s => s.Name == "EMAIL").EncodedValue;
     60                 var photoStr = info.FirstOrDefault(s => s.Name == "PHOTO") == null ? null : info.FirstOrDefault(s => s.Name == "PHOTO").EncodedValue;
     61                 if (photoStr != null)
     62                     linkMan.Img = await convertToImage(photoStr);
     63  
     64             }
     65             if (linkMan != null)
     66             {
     67                 VCards.Add(linkMan);
     68             }
     69         }
     70     }
     71  
     72     /// <summary>
     73     /// base64 To BitmapImage
     74     /// </summary>
     75     private async static Task<BitmapImage> convertToImage(string strimage)
     76     {
     77         try
     78         {
     79             byte[] bitmapArray;
     80             bitmapArray = Convert.FromBase64String(strimage);
     81             MemoryStream ms = new MemoryStream(bitmapArray);
     82             InMemoryRandomAccessStream randomAccessStream = new InMemoryRandomAccessStream();
     83             //将randomAccessStream 转成 IOutputStream
     84             var outputstream = randomAccessStream.GetOutputStreamAt(0);
     85             //实例化一个DataWriter
     86             DataWriter datawriter = new DataWriter(outputstream);
     87             //将Byte数组数据写进OutputStream
     88             datawriter.WriteBytes(bitmapArray);
     89             //在缓冲区提交数据到一个存储区
     90             await datawriter.StoreAsync();
     91  
     92             //将InMemoryRandomAccessStream给位图
     93             BitmapImage bitmapImage = new BitmapImage();
     94             bitmapImage.SetSource(randomAccessStream);
     95  
     96             return bitmapImage;
     97         }
     98         catch
     99         {
    100             return null;
    101         }
    102     }
    103  
    104     /// <summary>
    105     /// 进入到接受拖拽区
    106     /// </summary>
    107     private void VcBorder_DragOver(object sender, DragEventArgs e)
    108     {
    109         Debug.WriteLine("[Info] DragOver");
    110         //设置操作类型
    111         e.AcceptedOperation = DataPackageOperation.Copy;
    112  
    113         //设置提示文字
    114         e.DragUIOverride.Caption = "拖放此处即可添加文件 o(^▽^)o";
    115  
    116         ////是否显示拖放时的文字 默认为true
    117         //e.DragUIOverride.IsCaptionVisible = true;
    118  
    119         ////是否显示文件图标,默认为true
    120         //e.DragUIOverride.IsContentVisible = true;
    121  
    122         ////Caption 前面的图标是否显示。默认为 true
    123         //e.DragUIOverride.IsGlyphVisible = true;
    124  
    125         ////自定义文件图标,可以设置一个图标
    126         //e.DragUIOverride.SetContentFromBitmapImage(new BitmapImage(new Uri("ms-appx:///Assets/copy.jpg")));
    127     }
    128  
    129     /// <summary>
    130     /// 要删除的项
    131     /// </summary>
    132     LinkManModel DelItem;
    133  
    134     /// <summary>
    135     /// 开始拖拽Item 以准备删除
    136     /// </summary>
    137     private void VcList_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
    138     {
    139         DelItem = e.Items.FirstOrDefault() as LinkManModel;
    140     }
    141  
    142     /// <summary>
    143     /// 拖拽删除完成
    144     /// </summary>
    145     private void DelBorder_Drop(object sender, DragEventArgs e)
    146     {
    147         VCards.Remove(DelItem);
    148     }
    149  
    150     /// <summary>
    151     /// 进入拖拽删除区
    152     /// </summary>
    153     private void DelBorder_DragOver(object sender, DragEventArgs e)
    154     {
    155         //设置操作类型
    156         e.AcceptedOperation = DataPackageOperation.Move;
    157         e.DragUIOverride.Caption = "删除";
    158         e.DragUIOverride.IsContentVisible = false;
    159     }
    160      
    161 }
    162  
    163 public class LinkManModel
    164 {
    165     public string Name { get; set; }
    166  
    167     public string Email { get; set; }
    168  
    169     private string _Phone;
    170     public string Phone { get { return string.IsNullOrEmpty(_Phone)? null : Regex.Replace(_Phone, @"(?im)(d{3})(d{4})(d{4})", "$1***$3"); } set { _Phone = value; } }
    171     public BitmapImage Img { get; set; }
    172 }

    效果:

    推荐一个UWP开发群:53078485 大家可以进来一起学习

  • 相关阅读:
    Javajdbc
    Web Project添加Struts2框架
    CSS去除免费虚拟主机的广告心得分享
    List<T>采用delegate快速实现排序、查找等操作
    ASP.NET视频采集站核心技术分析(附送对付搜索引擎蜘蛛的贱招)
    Azure完整实例:在线日程表
    [发布]ClouderaCMS: 基于Windows Azure的开源CMS
    获取配置文件节点的值
    asp.net DataGrid排序
    checkbox 获取选中的值
  • 原文地址:https://www.cnblogs.com/Aran-Wang/p/4816232.html
Copyright © 2011-2022 走看看