UWPの制約に対処する
以上で、クリップボードの履歴を取得するClipboardHistoryData.TryUpdateAsync静的メソッドが出来ました。このメソッドは、まずアプリの初期化時に呼び出します。さて、その後は、いつ呼び出せばよいでしょう? ClipboardクラスにはHistoryChangedイベントがあって、履歴の変化を監視できます。このイベントを受けてTryUpdateAsync静的メソッドを呼び出せばよさそうです。
実際、従来のデスクトップアプリでは、クリップボードへのアクセスに制限はないので、HistoryChangedイベントハンドラーでTryUpdateAsync静的メソッドを呼び出すだけでよいです(WPFのMainWindow.xaml.cs)。
ところが、UWPアプリでは、クリップボードへアクセスできるのはアプリがアクティブになっているときだけです。アプリのウインドウが表示されていて、フォーカスを持っている状態でないと、アクセスできないのです。
そこで、UWPアプリでは、HistoryChangedイベントハンドラーでTryUpdateAsync静的メソッドを呼び出してみますが、履歴が取得できなかったらフラグを立てておいて、後でウインドウがアクティブになったときに改めてTryUpdateAsync静的メソッドを呼び出すようにします(次のコード、MainPage.xaml.cs)。
// 履歴取得失敗のフラグ
bool notGetClipboardHistoryYet = false;
// クリップボードの履歴に変化があったとき
// ※ ウインドウにフォーカスがないと取得に失敗する⇒フラグを立てておく
Clipboard.HistoryChanged += async (s, e) =>
{
if (await Data.ClipboardHistoryData.TryUpdateAsync()
!= ClipboardHistoryItemsResultStatus.Success)
notGetClipboardHistoryYet = true;
};
// ウインドウがアクティブになったとき
// ※ 取得失敗のフラグが立っていたら、取得してみる⇒成功したらフラグを倒す
CoreWindow.GetForCurrentThread().Activated += async (s, e) =>
{
if (notGetClipboardHistoryYet)
{
if (await Data.ClipboardHistoryData.TryUpdateAsync()
== ClipboardHistoryItemsResultStatus.Success)
notGetClipboardHistoryYet = false;
}
};
また、HistoryChangedイベントの他にも、HistoryEnabledChangedイベント(クリップボード履歴の利用可否が切り替えられたとき)とRoamingEnabledChangedイベント(クリップボードのローミングの利用可否が切り替えられたとき)でも履歴リストの内容が変化した可能性があるので、同じように対処します。なお、クリップボードそのものの内容の変化を監視するContentChangedイベントでも同様にします。
あとは、ClipboardHistoryData.Itemsコレクションを画面にデータバインディングしてやれば、アプリをクリックするなどしてアクティブにしたときに、履歴の表示が更新されるようになります(次の画像)。なお、Visual Studioからデバッグ実行しているときには、アクティブでなくてもクリップボードのデータが取れてしまうので、テストするときには気を付けてください。
