UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)

时间:2024-01-11 22:03:38

前面【UWP开发之Mvvmlight实践五:SuspensionManager中断挂起以及复原处理】章节已经提到过Template10,为了认识MvvmLight的区别特做了此实例。

原代码地址:https://github.com/NewBLife/UWP/tree/master/MvvmDemo/FileOperationDemo

应用主要功能:

  1. 本地任何文件多项选择添加
  2. 照相机图片添加
  3. 显示添加文件(.jpg.png.pdf.xls等)的缩略图
  4. 列表文件删除
  5. 默认程序显示添加后的文件

应用技术点:

  1. 汉堡菜单(随窗口大小自动收缩)
  2. 系统返回按钮操作
  3. StorageFile挂起复原
  4. 文件访问权限

应用截图如下:

====PC端====

主界面

UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)

点击【+】添加文件

UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)

点击列表任何文件(例如:0.PNG),使用默认应用打开文件

UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)

点击【头像】拍照

UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)

UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)

点击【Delete】可以删除列表文件

点击【设定】打开设定页面

UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)

====手机端====

主界面

UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)

点击【+】添加文件

UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)

选择任何文件(例如:list.pdf),使用默认应用打开文件

UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)

点击【头像】拍照

UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)

UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)

点击汉堡菜单选择【设定】

UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)

技术详解:

1.StorageFile文件的挂起复原

应用以外文件夹的文件挂起复原时如果通过路径获取StorageFile对象会出现以下异常,一般是通过令牌来做处理。

“System.UnauthorizedAccessException”类型的异常在 FileOperationDemo.exe 中发生,但未在用户代码中进行处理

其他信息: 拒绝访问。 (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
第一步:添加时从MRU中获取文件访问令牌
#region 获取 MRU 中文件的令牌
// 详细: https://msdn.microsoft.com/zh-cn/library/windows/apps/hh972603
// 应用外部文件访问时使用
_FileMruToken = StorageApplicationPermissions.FutureAccessList.Add(file);
#endregion

第二步:应用挂起时只保存令牌数据StorageFile属性JsonIgnore标记添加(StorageFile等对象无法反序列化复原)

/// <summary>
/// 文件信息
/// </summary>
[JsonIgnore]
public StorageFile File
{
get
{
return _File;
} set
{
Set(ref _File, value);
}
}
/// <summary>
/// 文件访问令牌
/// 挂起复原时使用
/// </summary>
[JsonProperty]
public string FileMruToken
{
get
{
return _FileMruToken;
} set
{
_FileMruToken = value;
}
}

第三步:复原时使用令牌获取StorageFile对象

// 应用外部文件
return await StorageApplicationPermissions.FutureAccessList.GetFileAsync(_FileMruToken);

2.默认应用打开文件时权限取得

// 默认应用打开文件
await Windows.System.Launcher.LaunchFileAsync(file);

直接赋值StorageFile对象到file时,是无法打开文件的,因为没有权限。这时也需要令牌从StorageApplicationPermissions.FutureAccessList获取StorageFile对象才能打开。

// 应用外部文件
return await StorageApplicationPermissions.FutureAccessList.GetFileAsync(_FileMruToken);

3.系统返回按钮事件注销时机

由于不想应用最后返回按下时关闭特加入此功能

/// <summary>
/// 返回按钮事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnBackRequested(object sender, BackRequestedEventArgs e)
{
e.Handled = true;
NavigationService.GoBack();
}

在OnNavigatedToAsync注册事件

public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> suspensionState)
{
try
{
if (suspensionState.Any())
{
FileList = SerializationService.Json.Deserialize<ObservableCollection<FileInfo>>(suspensionState[nameof(FileList)]?.ToString());
} // 注册系统返回按钮事件
SystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested;
await Task.CompletedTask;
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
Debug.WriteLine(ex.Source);
Debug.WriteLine(ex.StackTrace);
}
}
在OnNavigatingFromAsync注销事件
public override async Task OnNavigatingFromAsync(NavigatingEventArgs args)
{
args.Cancel = false;
// 注销系统返回按钮事件
SystemNavigationManager.GetForCurrentView().BackRequested -= OnBackRequested;
await Task.CompletedTask;
}