首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

Windows 8 選取器進階:CachedFileUpdater 離線快取檔案更新機制

     編輯:關於.NET

前言

CachedFileUpdater (快取檔案更新程式) 讓應用程式能為其他應用程式提供的檔案建立「即時同步」關係。當應用程式透過檔案開啟選取器選取某檔案時,提供者可將該檔案標記為需由 CachedFileUpdater 更新 (Local 模式) 或由應用程式自行更新並通知 Updater (Remote 模式)。本文完整示範提供者端與呼叫端的雙向實作。

一、提供者端實作 (獨立專案)

1. 檔案開啟選取器

在 Manifest 宣告「檔案開啟選取器」,支援特定副檔名。啟動時接收 FileOpenPickerActivatedEventArgs,取得 FileOpenPickerUI,呼叫 AddFile 並使用 CachedFileUpdater.SetUpdateInformation 關聯更新資訊。

XAML

<Page x:Class="CachedFileUpdaterProvider.MyOpenPicker" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:CachedFileUpdaterProvider" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Grid Background="Transparent">
<StackPanel Margin="120 0 0 0">
<TextBlock Name="lblMsg" FontSize="14.667" />
<Button Name="btnPickCachedFileLocal" Content="提供一個由 Local 更新的 CachedFile(由 CachedFileUpdater 更新 CachedFile)" Click="btnPickCachedFileLocal_Click_1" Margin="0 10 0 0" />
<Button Name="btnPickCachedFileRemote" Content="提供一個由 Remote 更新的 CachedFile(由 app 更新 CachedFile)" Click="btnPickCachedFileRemote_Click_1" Margin="0 10 0 0" />
</StackPanel>
</Grid>
</Page>

程式碼後置

using System;
using Windows.ApplicationModel.Activation;
using Windows.Storage;
using Windows.Storage.Pickers.Provider;
using Windows.Storage.Provider;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace CachedFileUpdaterProvider
{
    public sealed partial class MyOpenPicker : Page
    {
        private FileOpenPickerUI _fileOpenPickerUI;
        public MyOpenPicker()
        {
            this.InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            var args = (FileOpenPickerActivatedEventArgs)e.Parameter;
            _fileOpenPickerUI = args.FileOpenPickerUI;
            _fileOpenPickerUI.Title = "自訂檔案開啟選取器";
        }

        private async void btnPickCachedFileLocal_Click_1(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(@"webabcdCachedFileUpdaterLocal.txt", CreationCollisionOption.ReplaceExisting);
            string textContent = "I am webabcd";
            await FileIO.WriteTextAsync(file, textContent);
            CachedFileUpdater.SetUpdateInformation(file, "cachedFileLocal", ReadActivationMode.BeforeAccess, WriteActivationMode.NotNeeded, CachedFileOptions.RequireUpdateOnAccess);
            lblMsg.Text = "選擇的檔案: " + file.Name;
            AddFileResult result = _fileOpenPickerUI.AddFile("myFile", file);
        }

        private async void btnPickCachedFileRemote_Click_1(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(@"webabcdCachedFileUpdaterRemote.txt", CreationCollisionOption.ReplaceExisting);
            string textContent = "I am webabcd";
            await FileIO.WriteTextAsync(file, textContent);
            CachedFileUpdater.SetUpdateInformation(file, "cachedFileRemote", ReadActivationMode.NotNeeded, WriteActivationMode.AfterWrite, CachedFileOptions.RequireUpdateOnAccess);
            lblMsg.Text = "選擇的檔案: " + file.Name;
            AddFileResult result = _fileOpenPickerUI.AddFile("myFile", file);
        }
    }
}

2. 快取檔案更新程式

在 Manifest 宣告「快取檔案更新程式」。啟動時接收 CachedFileUpdaterActivatedEventArgs,取得 CachedFileUpdaterUI。處理 FileUpdateRequested (Local 模式顯示 UI 讓使用者確認更新,Remote 模式直接回報 Complete) 與 UIRequested (顯示更新 UI)。

XAML

<Page x:Class="CachedFileUpdaterProvider.MyCachedFileUpdater" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:CachedFileUpdaterProvider" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Grid Background="Transparent">
<StackPanel Margin="120 0 0 0">
<TextBlock Name="lblMsg" FontSize="14.667" />
<Button Name="btnUpdate" Content="更新 CachedFile(由 CachedFileUpdater 更新 CachedFile)" Click="btnUpdate_Click_1" Margin="0 10 0 0" />
</StackPanel>
</Grid>
</Page>

程式碼後置

using System;
using Windows.ApplicationModel.Activation;
using Windows.Storage;
using Windows.Storage.Provider;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace CachedFileUpdaterProvider
{
    public sealed partial class MyCachedFileUpdater : Page
    {
        private CachedFileUpdaterUI _cachedFileUpdaterUI;
        private FileUpdateRequest _fileUpdateRequest;
        private CoreDispatcher _dispatcher = Windows.UI.Xaml.Window.Current.Dispatcher;

        public MyCachedFileUpdater()
        {
            this.InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            var args = (CachedFileUpdaterActivatedEventArgs)e.Parameter;
            _cachedFileUpdaterUI = args.CachedFileUpdaterUI;
            _cachedFileUpdaterUI.Title = "快取檔案更新程式";
            _cachedFileUpdaterUI.FileUpdateRequested += _cachedFileUpdaterUI_FileUpdateRequested;
            _cachedFileUpdaterUI.UIRequested += _cachedFileUpdaterUI_UIRequested;
        }

        async void _cachedFileUpdaterUI_UIRequested(CachedFileUpdaterUI sender, object args)
        {
            await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
                Windows.UI.Xaml.Window.Current.Content = this;
                lblMsg.Text = "FileUpdateStatus: " + _fileUpdateRequest.Status.ToString();
            });
        }

        void _cachedFileUpdaterUI_FileUpdateRequested(CachedFileUpdaterUI sender, FileUpdateRequestedEventArgs args)
        {
            _fileUpdateRequest = args.Request;
            FileUpdateRequestDeferral fileUpdateRequestDeferral = _fileUpdateRequest.GetDeferral();
            if (_cachedFileUpdaterUI.UpdateTarget == CachedFileTarget.Local)
            {
                if (_cachedFileUpdaterUI.UIStatus == UIStatus.Hidden)
                {
                    _fileUpdateRequest.Status = FileUpdateStatus.UserInputNeeded;
                    fileUpdateRequestDeferral.Complete();
                }
            }
            else if (_cachedFileUpdaterUI.UpdateTarget == CachedFileTarget.Remote)
            {
                _fileUpdateRequest.Status = FileUpdateStatus.Complete;
                fileUpdateRequestDeferral.Complete();
            }
        }

        private async void btnUpdate_Click_1(object sender, RoutedEventArgs e)
        {
            FileUpdateRequestDeferral fileUpdateRequestDeferral = _fileUpdateRequest.GetDeferral();
            await FileIO.AppendTextAsync(_fileUpdateRequest.File, Environment.NewLine + "由 CachedFileUpdater 更新:" + DateTime.Now.ToString());
            string fileContent = await FileIO.ReadTextAsync(_fileUpdateRequest.File);
            lblMsg.Text = "檔案名: " + _fileUpdateRequest.File.Name;
            lblMsg.Text += Environment.NewLine;
            lblMsg.Text += "檔案內容: " + fileContent;
            _fileUpdateRequest.Status = FileUpdateStatus.Complete;
            fileUpdateRequestDeferral.Complete();
            btnUpdate.IsEnabled = false;
        }
    }
}

3. App.xaml.cs 判斷啟動類型

protected override void OnFileOpenPickerActivated(FileOpenPickerActivatedEventArgs args)
{
    var rootFrame = new Frame();
    rootFrame.Navigate(typeof(MyOpenPicker), args);
    Window.Current.Content = rootFrame;
    Window.Current.Activate();
}

protected override void OnCachedFileUpdaterActivated(CachedFileUpdaterActivatedEventArgs args)
{
    var rootFrame = new Frame();
    rootFrame.Navigate(typeof(MyCachedFileUpdater), args);
    Window.Current.Content = rootFrame;
    Window.Current.Activate();
}

二、呼叫端應用程式使用 CachedFileUpdater

透過 FileOpenPicker 選取提供者提供的檔案,儲存 FutureAccessList 權杖。Local 模式下讀取檔案會自動觸發 Updater 更新;Remote 模式下呼叫 CachedFileManager.DeferUpdates -> 修改檔案 -> CompleteUpdatesAsync 完成更新並取得狀態。

XAML

<Page x:Class="XamlDemo.Picker.CachedFileUpdaterDemo" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Picker" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Grid Background="Transparent">
<StackPanel Margin="120 0 0 0">
<TextBlock Name="lblMsg" FontSize="14.667" />
<Button Name="btnGetCachedFile" Content="開啟 Provider 提供的 CachedFile" Click="btnGetCachedFile_Click_1" Margin="0 10 0 0" />
<Button Name="btnReadCachedFile" Content="由 CachedFileUpdater 更新檔案" Click="btnReadCachedFile_Click_1" Margin="0 10 0 0" />
<Button Name="btnWriteCachedFile" Content="由 app 更新檔案" Click="btnWriteCachedFile_Click_1" Margin="0 10 0 0" />
</StackPanel>
</Grid>
</Page>

程式碼後置

using System;
using Windows.Storage;
using Windows.Storage.AccessCache;
using Windows.Storage.Pickers;
using Windows.Storage.Provider;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace XamlDemo.Picker
{
    public sealed partial class CachedFileUpdaterDemo : Page
    {
        private string _cachedFileToken;
        public CachedFileUpdaterDemo()
        {
            this.InitializeComponent();
        }

        private async void btnGetCachedFile_Click_1(object sender, RoutedEventArgs e)
        {
            if (XamlDemo.Common.Helper.EnsureUnsnapped())
            {
                FileOpenPicker openPicker = new FileOpenPicker();
                openPicker.FileTypeFilter.Add(".txt");
                StorageFile file = await openPicker.PickSingleFileAsync();
                if (file != null)
                {
                    _cachedFileToken = StorageApplicationPermissions.FutureAccessList.Add(file);
                    string fileContent = await FileIO.ReadTextAsync(file);
                    lblMsg.Text = "檔案名: " + file.Name;
                    lblMsg.Text += Environment.NewLine;
                    lblMsg.Text += "檔案內容: " + fileContent;
                }
                else
                {
                    lblMsg.Text = "取消了";
                }
            }
        }

        private async void btnReadCachedFile_Click_1(object sender, RoutedEventArgs e)
        {
            if (!string.IsNullOrEmpty(_cachedFileToken))
            {
                StorageFile file = await StorageApplicationPermissions.FutureAccessList.GetFileAsync(_cachedFileToken);
                string fileContent = await FileIO.ReadTextAsync(file);
                lblMsg.Text = "檔案名: " + file.Name;
                lblMsg.Text += Environment.NewLine;
                lblMsg.Text += "檔案內容: " + fileContent;
            }
        }

        private async void btnWriteCachedFile_Click_1(object sender, RoutedEventArgs e)
        {
            if (!string.IsNullOrEmpty(_cachedFileToken))
            {
                StorageFile file = await StorageApplicationPermissions.FutureAccessList.GetFileAsync(_cachedFileToken);
                CachedFileManager.DeferUpdates(file);
                await FileIO.AppendTextAsync(file, Environment.NewLine + "由 app 更新:" + DateTime.Now.ToString());
                FileUpdateStatus status = await CachedFileManager.CompleteUpdatesAsync(file);
                lblMsg.Text = status.ToString();
                lblMsg.Text += Environment.NewLine;
                if (status == FileUpdateStatus.Complete)
                {
                    string fileContent = await FileIO.ReadTextAsync(file);
                    lblMsg.Text += "檔案名: " + file.Name;
                    lblMsg.Text += Environment.NewLine;
                    lblMsg.Text += "檔案內容: " + fileContent;
                }
            }
        }
    }
}

總結

  • Local 模式:由 CachedFileUpdater 主動更新檔案內容,適用於雲端同步、版本控制等提供者主導場景。
  • Remote 模式:由呼叫端應用程式修改檔案,完成後通知 Updater,適用於編輯器、註解工具等消費者主導場景。
  • 完整流程涉及三方:呼叫端 App、提供者、CachedFileUpdater 系統中介者,透過 contentId 識別同一檔案的不同版本。
  • Manifest 需分別宣告「檔案開啟選取器」與「快取檔案更新程式」兩項宣告。

[原始碼下載]:https://files.cnblogs.com/webabcd/Windows8.rar

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved