shuhelohelo’s blog

Xamarin.Forms多めです.

WPFでアクションセンターに通知を表示

Windows10にはアクションセンターがあります。 メールやSlackなどのメッセージ受信をぴろーんと通知してくるあれです。 これをWPFアプリから使いたいと思いました。

何年か前にもWPFアプリで通知機能を使いたいなと思ったのですが、そのときはなにやらいろいろと大変そうだったのでやめた記憶がうっすらとあります。

それが、最近になって割と簡単に使えるようになったとかずきさんのブログで知って、改めてやってみたくなった次第です。

WPFアプリからアクションセンターに通知を出す手順については以下のページに詳しく書かれていて、その手順どおりにやっただけです。 ほんとありがとうございます。

www.thomasclaudiushuber.com

UWPからは簡単

さて、このアクションセンターへの通知の表示を行うにはWinRT APIを使う必要があります。 UWPアプリからは非常に簡単に使うことができます。

例えば、空のUWPアプリを作成してボタンを配置し、コードビハインドのClickイベントハンドラに以下のコードを貼り付けて実行してみましょう。 このコードは上記のサイトに掲載されているサンプルコードです。

            string title = "The current time is";
            string timeString = $"{DateTime.Now:HH:mm:ss}";
            string thomasImage = "https://www.thomasclaudiushuber.com/thomas.jpg";

            string toastXmlString =
            $@"<toast><visual>
            <binding template='ToastGeneric'>
            <text>{title}</text>
            <text>{timeString}</text>
            <image src='{thomasImage}'/>
            </binding>
        </visual></toast>";

            var xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(toastXmlString);

            var toastNotification = new ToastNotification(xmlDoc);

            var toastNotifier = ToastNotificationManager.CreateToastNotifier();
            toastNotifier.Show(toastNotification);

必要なusingは以下のとおりです。

using System;
using System.Windows;
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;

ボタンを押すと、ぴろーん。 イケメンの写真とともに現在時刻が通知されます。

f:id:shuhelohelo:20190510111357p:plain

WPFだとひと手間必要(本題)

前述のサイトではWPF .NET Frameworkを使っていますが、せっかくなのでWPF Coreでやってみます。

まずはWPF Coreのプロジェクトを作成します。 f:id:shuhelohelo:20190510113339p:plain

次にMicrosoft.Windows.SDK.ContractsをNugetからインストール。 このあたりの手順についてはかずきさんのブログが詳しいかなと思います。

f:id:shuhelohelo:20190509200303p:plain

ツール > オプションを選択してオプションウィンドウを表示します。

設定項目の中からNugetパッケージマネージャーを選択します。

パッケージの管理で、規定のパッケージ管理形式にPackageReferenceを選択します。 f:id:shuhelohelo:20190509200816p:plain

ここまででWPFアプリからWinRT APIを呼び出すことができるようになりました。

このWPFアプリにもボタンを一つ配置してClickイベントハンドラに前述のサンプルコードを貼り付けましょう。 必要なusingを追加してビルドしましょう。 通ったはずです。

では実行してボタンを押すと、ぴろーんといくかと思いきや以下のエラーが。

f:id:shuhelohelo:20190509201455p:plain

このエラーがでるのは前述の英語サイトでは予定どおりということで以下のように説明されていました。

The problem here is that your WPF application doesn’t have a package identity. A UWP app has a package identity, and it is installed in Windows 10 with that identity. But a WPF app doesn’t have such an identity, so let’s create one.

ざっくりいうと、

原因は、WPFはアプリはパッケージ識別子がないため。UWPアプリはパッケージ識別子があって、アプリと識別子はWindows10に一緒にインストールされる。でも、WPFアプリはその識別子がない。だから作っちゃう。

ということです。

これについてはかずきさんの以下の記事のまとめでも書かれているとおり、「通知」は識別子が割り当てられないと使えないAPIということでした。

blog.okazuki.jp

識別子がない問題を解決する

ではこの識別子の問題をどうやって解決するかというと、Windows アプリケーションパッケージプロジェクトを使ってWPFアプリをストアアプリ(UWPアプリ)としてパッケージ化してやります。

デスクトップアプリのストアアプリ化(?)の手順については公式サイトが詳しいです。

docs.microsoft.com

Windows アプリケーションパッケージプロジェクト」の追加

ではまず、ソリューションにプロジェクトをもう一つ追加します。

f:id:shuhelohelo:20190509202116p:plain

プロジェクトテンプレートとして、Windows アプリケーションパッケージプロジェクトを選択します。プロジェクトタイプをUWPで絞り込むと見つけやすいかと思います。 名前は適当に。

f:id:shuhelohelo:20190509202219p:plain

新しく追加したプロジェクトのアプリケーションコンテキストメニューから参照の追加を選択します。

f:id:shuhelohelo:20190509202627p:plain

WPF Coreプロジェクトを参照に追加します。

f:id:shuhelohelo:20190509202759p:plain

こんなエラーが。 f:id:shuhelohelo:20190509202907p:plain

TargetPlatformVersionが合わない。なるほど。

確かに、先程インストールしたMicrosoft.Windows.SDK.Contractsのバージョンは最新(プレビュー)の10.0.18362.0でした。

それに対してWindows アプリケーションパッケージプロジェクトの作成時に選択したバージョンは10.0.17763.0でした。

というわけで、NugetでMicrosoft.Windows.SDK.Contractsのバージョンを10.0.17763.0にします。

f:id:shuhelohelo:20190509203053p:plain

これで準備完了です。

実行

それでは実行します。 ウィンドウが表示されて、ボタンを押すと。

ぴろーん。 f:id:shuhelohelo:20190509211835p:plain

イケメンが現在時刻を教えてくれます。

おわりに

設定ファイルを手動で変更したり、必要なファイルを手動で配置したりといったことなしに、Nugetでのパッケージ追加、設定変更、参照追加など全ての作業をVisual Studioで完了でき、とても「簡単」にWPFアプリからアクションセンターに通知を表示できたと思います。

Windows アプリケーションパッケージプロジェクトWPFアプリを包むところがトリッキーといえばトリッキーですが、やってることはプロジェクトの参照だけなので難しいことはありません。