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 大家可以进来一起学习

  • 相关阅读:
    hdu 5224 Tom and paper 水题
    2015 UESTC 搜索专题N题 韩爷的梦 hash
    2015 UESTC 搜索专题M题 Palindromic String 马拉车算法
    2015 UESTC 搜索专题K题 秋实大哥の恋爱物语 kmp
    2015 UESTC 搜索专题J题 全都是秋实大哥 kmp
    2015 UESTC 搜索专题F题 Eight Puzzle 爆搜
    2015 UESTC 搜索专题E题 吴队长征婚 爆搜
    2015 UESTC 搜索专题D题 基爷的中位数 二分
    2015 UESTC 搜索专题C题 基爷与加法等式 爆搜DFS
    2015 UESTC 搜索专题B题 邱老师降临小行星 记忆化搜索
  • 原文地址:https://www.cnblogs.com/Aran-Wang/p/4816232.html
Copyright © 2011-2022 走看看