在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 }
其中有三個比較重要的:app
要想讓元素接受拖拽對象到它本身自己,咱們要設置元素的AllowDrop屬性爲True,拖拽會觸發四種事件:DragEnter(進入接受拖拽的範圍)、DragOver(處於接受拖拽範圍)、Drop(鬆開鼠標)、DragLeave(離開接受拖拽的範圍),總體的拖拽流程是這樣的:dom
而咱們須要訂閱該元素的Drop、DragOver兩個事件,DragOver事件會在拖拽對象到該元素時一直被觸發,而當鼠標鬆開拖拽時會觸發Drop事件。async
接下來,咱們演示下從系統磁盤文件夾拖拽一些vcf聯繫人到咱們的App中。ide
界面上放置三個區域:接受拖拽區、文件顯示區、拖拽刪除區學習
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>
後臺代碼:ui
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 }
效果:this
推薦一個UWP開發羣:53078485 你們能夠進來一塊兒學習spa