C#、WPF、MVVMによるトースト通知
Published: 2023-12-01 11:56:39

[デスクトップ・ノーティフィケーションは](https://www.pubnub.com/use-case/alerts-and-push-notifications/)、リアルタイムの[イベント・ドリブン・アプリに](https://www.pubnub.com/guides/event-driven-architecture/)必要な機能になってきていることにお気づきだろうか。Webサービスでは、バックエンドのシグナルや他のユーザーからのメッセージが発生すると、ユーザーに通知する必要があります。

このガイドでは、**C#と** **WPF**、**Windows Forms**、**UWPを**使用してWindowsデスクトップアプリケーションを構築しようとしているソフトウェアエンジニアやフルスタックソフトウェア開発者を対象に、**MVVMデザインパターンを**使用してデスクトッププッシュ通知の**フロントエンドとバックエンドの**コードを構築する方法を説明します。

このガイドの主役は**PubNubの** [**リアルタイムメッセージングAPI**](https://www.pubnub.com/docs/channels/overview)です。このAPIを使用すると、クライアントやサーバーは世界中のどこからでも、任意の数のデバイス、Webアプリ、モバイルアプリにリアルタイムでシグナルを送信できます。

**トースト通知に必要なプログラミング言語の概要**
--------------------------

このチュートリアルでは、さまざまなコーディング言語とアルゴリズム言語を使用します。まず始めに、それらのプログラマー言語を簡単に定義し、それからワークフローのプロセスに飛び込みます。

**WPFとは？**
----------

これから一緒に実行するコード例は、[Windows Presentation Foundation](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/getting-started/introduction-to-wpf-in-vs?view=netframeworkdesktop-4.8)またはWPFを使って書かれています。過去10年間、WPFは**C#と.NET Frameworkで**WindowsデスクトップWebアプリを開発するためのベストチョイスのサブシステムでした。ユーザーインターフェイス開発には[XAMLを](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/fundamentals/xaml?view=netdesktop-5.0)使用し、各ビューにはC#[Code Behindsを](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/advanced/code-behind-and-xaml-in-wpf?view=netframeworkdesktop-4.8)使用するという点で、Windows Formsに似ています。

**簡単なヒント**

このチュートリアルでは、MVVMパターンを使用するため、できるだけ多くのコードをコードビハインドの外に置くようにします。そのため、通常はコードビハインドに記述するコードを**ViewModel クラスに**記述します。

**MVVMアーキテクチャとは？**
------------------

**Model-View-ViewModel**、またはMVVMは、ユーザー向けのアプリケーションにおいて、UI開発とバックエンド開発を**分離**するためのデザインパターンです。このパターンを構成する**3つのコンポーネントが**あります。

### WPFAppsのコンポーネントは何ですか？

WPFappsの場合、これらのコンポーネントは次のとおりです：

-   ビュー - [XAMLとCodeBehinds](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/advanced/code-behind-and-xaml-in-wpf?view=netframeworkdesktop-4.8)
    
-   ViewModels - 状態管理と、ModelとViewの間を移動するデータを制御するためのC#コード。
    
-   モデル - C#クラス、データストレージ、ビジネスロジック。
    

![](https://images.ctfassets.net/3prze68gbwl1/655JWYGQsi4tlNkqAhlEYq/197b20ffa25e393fc71d3959804c5d13/pubnub-mvvm-diagram.png)

**C#デスクトップ通知**
--------------

OSを意識した通知のためのWindowsデスクトップのソリューションは、**Toast Notification**クラスです。Toast通知はWindows UI Notificationクラスに統合されています。

### Toast通知とは？

この例では、Toast 通知を使用します。Toast通知は、自動的に表示され、期限切れになるようにプログラムされた小さなポップアップです。通常は控えめで、ユーザーからのアクションを必要としません。また、ユーザーの活動を停止させることもありません。

このタイプの自動プッシュ通知は、デスクトップポップアップに最適です。しかし、WPFでのToastのサポートは豊富ではありません。

#### **Toast通知のプロのヒント**

このシナリオの回避策は、WPFappが通知を含むことができるように、独自のトーストデスクトップ通知ユーザーインターフェイスを構築することです。このような通知は、ViewModel コード内の従来の C# イベントを使用して、 **いつでもトリガー**できます。

![](https://images.ctfassets.net/3prze68gbwl1/5xBfgEWMPTg4WpQKODQXXq/080ec85b78673760b19f4091be8f608d/pubnub-wpf-notification.png)

これから一緒に作るサンプルは、C#の通知を使ったWPFappです。

**親ウィンドウが1つ**あり、ボタンが1つあります。ボタンをクリックすると、ネットワークへの**JSON**データのPubNub[パブリッシュが](https://www.pubnub.com/docs/sdks/c-sharp/)トリガーされます。アプリケーションはまた、Publishコードと**同じチャネルとAPIキー**（無料の[PubNubAPI](https://dashboard.pubnub.com/signup)キー）を使用してPubNubに**サブスクライブ**します。

PubNubサブスクライブコードは、新しいメッセージがパブリッシュされるたびに、デスクトップにポップアッププッシュ通知を作成する**C#イベントを**トリガします。PubNubメッセージの待ち時間は、発行者と購読者の距離に関係なく、**一般的に80〜100ミリ秒**です。

![](https://images.ctfassets.net/3prze68gbwl1/3867ZSWtcQs2csl35ZvUzr/5b32af712a7a3656089dd5d837f4ad74/pubnub-desktop-notification.png)

PubNubは、**70以上のクライアント** [**SDKを持って**](https://www.pubnub.com/docs/sdks)いるので、任意のインターネット対応デバイスは、この図に交換することができます。

C#とMVVMによるWPFTutorial通知チュートリアルプロジェクト
------------------------------------

PubNubメッセージングのパワーとWPFデスクトップ通知のためのソリューションを実証するために、独自のC＃通知アプリを構築するつもりです。以下はMVVMプロジェクトのファイル構造です：

![](https://images.ctfassets.net/3prze68gbwl1/FfGomoqHd2m9ZGyqYvFQS/dcd2e6ffe9856e1842f7b227573db292/wpf-pubnub-project.png)

_このチュートリアルで参照するコードはすべて_ [**_GitHubで_**](https://github.com/ajb413/wpf-pubnub-desktop-notifications)**_オープンソースとして公開_** されています_。_

_アプリを実行_ するには、**_永久無料の_**[**_PubNubAPIキーを_**](https://dashboard.pubnub.com/signup)_取得する必要が_ あります_。_

**PublishキーとSubscribeキーを**ソースコードに追加してください！

**MVVMで始めるデスクトップ通知の構築**
-----------------------

1.ゼロから始める場合は、Visual**Studio**[（無料](https://visualstudio.microsoft.com/vs/community/)）を開き、新しい**WPFweb**アプリケーションを作成します。**File -> New -> Projectをクリック**します。

![](https://images.ctfassets.net/3prze68gbwl1/Cy9BHqBZ6O23j8ntXQ5xG/cd1c8e30743790662c6639dcf7d44116/wpf-new-project-1.png)

2.**ソリューションエクスプローラーで**新規プロジェクトファイルを右クリックし、**NuGetパッケージの管理を**クリックします。**PubNubをインストール**する必要があります。

![](https://images.ctfassets.net/3prze68gbwl1/33PqCdHI6MLEgUWfIqjKec/eb638d0eb4b331ea3efd210d13eaed9c/install-pubnub-sdk-csharp.png)

3.先ほどの**スクリーンショットの**ように、**プロジェクトのルートに**フォルダを作成します。これらのフォルダは**Model、View、ViewModel**です。Viewフォルダに2つの新しいXAMLウィンドウ、**Main Windowと** **Notification Window**を作成します。

**通知ビルドをXAMLで続ける**
------------------

作成した2つのビューファイルのXAMLです。これが親ウィンドウと通知ウィンドウの**UIに**なります。

MainWindow.xaml

<Window x:Class="WPF\_PubNub.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:vm="clr-namespace:WPF\_PubNub.VM" xmlns:local="clr-namespace:WPF\_PubNub" mc:Ignorable="d"        
  
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" Title="{Binding WindowName}" Height="300" Width="400"> <Window.DataContext> <vm:PubNubVM /> </Window.DataContext> <i:Interaction.Triggers> <i:EventTrigger EventName="Loaded"> <ei:CallMethodAction TargetObject="{Binding}"MethodName="MainWindowLoaded"/> </i:EventTrigger> </i:Interaction.Triggers> <!--Loaded="{Binding OnWindowLoaded}"--> <Grid > <StackPanel Name="stackPanel2" Grid.Column="1" Grid.Row="0" Background="White" > <Border CornerRadius="5" BorderBrush="Gray" BorderThickness="2" HorizontalAlignment="Center" > <Button Width="{Binding ButtonWidth}" 
                Height="{Binding ButtonHeight}"Content="{バインディング ButtonContent}"Background="#FFF3F0F0"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <ei:CallMethodAction TargetObject="{Binding}"メソッド名="PublishMessage"/> </i:EventTrigger> </i:Interaction.Triggers> </Button> </Border> </StackPanel> </Grid> </Window> <Window

**通知ウィンドウ.xaml**

<Window x:Class="Toast.NotificationWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" WindowStyle="None" 
        Height="116.783" Width="319.93" Background="#FF110505" > <Grid> <Grid RenderTransformOrigin="0,1" > <!-- Animation --> <Grid.Triggers> <EventTrigger RoutedEvent="FrameworkElement.Loaded"> <BeginStoryboard> <Storyboard> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"> <SplineDoubleKeyFrame KeyTime="0:0:0" Value="0"/> <SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)"> <SplineDoubleKeyFrame KeyTime="0:0:2" Value="1"/> <SplineDoubleKeyFrame KeyTime="0:0：4" Value="0"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger> </Grid.Triggers> <Grid.RenderTransform> <ScaleTransform ScaleY="1" /> </Grid.RenderTransform> <！-- Notification area --> <Border BorderThickness="1" Margin="0,0,0,10" Background="#FF17161F" BorderBrush="Black" CornerRadius="10"> <StackPanel Margin="20,9"> <TextBlock TextWrapping="Wrap" Margin="21,5,23,5" x：Name="NotifText" Foreground="White" Background="Black" Height="75"/> </StackPanel> </Border> <Image HorizontalAlignment="Left" Height="37" VerticalAlignment="Top" Width="42" Source="iconMail.JPG" Margin="0,16,0,0"/> </Grid> <Button BorderThickness="0" HorizontalAlignment="Left" Margin="270,0,0,0" Click="Button\_Click\_Close" VerticalAlignment="Top" Background="{x:Null}"幅="42" 高さ="43"> <画像ソース="CloseBtn.JPG" 高さ="39" 幅="28" /> </Button> </Grid> <//Window> <Window

### C#通知ウィンドウのコード例

[通知](https://github.com/ajb413/wpf-pubnub-desktop-notifications/blob/master/WPF_PubNub/View/NotificationWindow.xaml.cs)ウィンドウの **C#コード** 例です。すべてのコードはUI固有のものです。これは "Toast "通知に似ています。

using System; using System.Windows; using System.Windows.Threading; namespace Toast { /// <summary> /// NotificationWindow.xaml /// NotificationWindow.xamlのインタラクションロジック。xaml /// </summary> public partial class NotificationWindow : Window { public NotificationWindow() { InitializeComponent(); Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action() => { var workingArea = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea;
                var transform = PresentationSource.FromVisual(this).CompositionTarget.TransformFromDevice;
                var corner = transform.Transform(new Point(workingArea.Right, workingArea.Bottom));
                Left = corner.X - ActualWidth;
                Top = corner.Y - ActualHeight;
            }));
        }
 
        //Close the notification window
        private void Button\_Click\_Close(object sender, RoutedEventArgs e)
        {
            Close();
        }
    }
}

**C#、WPF、MVVM 通知を構築する最後のステップ**
------------------------------

1.  ViewModelフォルダに**PubNubVM.csを**作成します。**PubNubVM.csは** **Modelコードと** **Viewコードの**間のファシリテーターとなります。このファイルのコードは[ここに](https://github.com/ajb413/wpf-pubnub-desktop-notifications/blob/master/WPF_PubNub/ViewModel/PubNubVM.cs)あります。
    
2.  Modelフォルダには、PubNub発行/購読APIと対話するための**PubNubHelper.cs**クラスを作成します。 **PubNubの初期化コードには**、**必ず独自の** [**PubNubAPIキーを**](https://dashboard.pubnub.com/signup) **入力して** ください。
    
3.  ファイル内に"\_\_YOUR\_PUBNUB\_PUBLISH\_KEY\_HERE\_\_"と"\_\_YOUR\_PUBNUB\_SUBSCRIBE\_KEY\_HERE\_\_"があります。これらの文字列リテラルをあなたのキーに置き換えてください。
    

using Newtonsoft.Json; using PubnubApi; using System; using System.Windows; using Toast; namespace WPF\_PubNub.public class PubNubHelper { Pubnub pubnub; private readonly string ChannelName = "win-notification"；
        public void Init() { //PNConfiguration pnConfiguration = new PNConfiguration { PublishKey = "\_\_YOUR\_PUBNUB\_PUBLISH\_KEY\_HERE\_\_", SubscribeKey = "\_\_YOUR\_PUBNUB\_SUBSCRIBE\_KEY\_HERE\_\_", Secure = true }; pubnub = new Pubnub(pnConfiguration); //Subscribe pubnub.Subscribe<string>() .Channels(new string\[\] { ChannelName }) .WithPresence() .Execute(); } //メッセージを発行する public void Publish() { JsonMsg Person = new JsonMsg { Name = "John Doe", Description = "Description", Date = DateTime.Now.ToString() }; //文字列に変換 arrayMessage = JsonConvert.SerializeObject(Person); pubnub.Publish() .Channel(ChannelName) .Message(arrayMessage) .Async(new PNPublishResultExt((result, status) => {})); } //チャンネルを聞く public void Listen() { SubscribeCallbackExt listenerSubscribeCallack = new SubscribeCallbackExt( (pubnubObj, message) => { //UIスレッドから通知ウィンドウを呼び出す Application.Current.Dispatcher.Invoke(new Action(() => { //WIN-10トーストのようなWPFウィンドウメッセージとしてメッセージを表示する NotificationWindow ts = new NotificationWindow(); //メッセージをJSONに変換する JsonMsg bsObj = JsonConvert.DeserializeObject<JsonMsg>(message.Message.ToString()); string messageBoxText = "Name：" + bsObj.Name + Environment.NewLine + "説明：" + bsObj.Description + Environment.NewLine + "Date: " + bsObj.Date; ts.NotifText.Text = messageBoxText; ts.Show();
                }));
            },
            (pubnubObj, presence) => {
                // handle incoming presence data
            },
            (pubnubObj, status) => {
                // the status object returned is always related to subscribe but could contain
                // information about subscribe, heartbeat, or errors
                // use the PNOperationType to switch on different options
            });
 
            pubnub.AddListener(listenerSubscribeCallack);
        }
    }
}

**Pro Tip: Modelフォルダには、JsonMsg.csクラスも必要** [**です**](https://github.com/ajb413/wpf-pubnub-desktop-notifications/blob/master/WPF_PubNub/Model/JsonMsg.cs)**。** [**WPFプロジェクト**](https://github.com/ajb413/wpf-pubnub-desktop-notifications/blob/master/WPF_PubNub/WPF_PubNub.csproj)・**ファイルで参照されているNuGetパッケージは必ず追加して** ください**。また** 、[**Viewフォルダ**](https://github.com/ajb413/wpf-pubnub-desktop-notifications/tree/master/WPF_PubNub/View)には**いくつかのJPG画像** ファイルがあります**。これらの画像はカスタムメイドの通知ウィンドウに表示されます。必ずプロジェクトのViewフォルダに追加してください。**

4.プロジェクトを実行します！Trigger Notification Window "ボタンをクリックしてください。デスクトップの右下にカスタム通知が表示されます！これはPubNubを利用しているため、このアプリケーションを複数のマシンで実行している場合、各ボタンをクリックするたびにすべてのマシンに通知が表示されます。

![](https://images.ctfassets.net/3prze68gbwl1/6uxw74cdFfaWHFIVIeT1a/ab14d1b074bda88a5d335a8069df95bc/pubnub-wpf-window.png)

他の[PubNubSDKと](https://www.pubnub.com/docs/sdks)クライアントデバイスを使用することで、通知システムは言語やデバイスに依存しません。

### **デスクトップトースト通知を始める**

このデスクトップ通知パターンは、ユーザーエクスペリエンスの向上を目的としたカスタムプッシュ通知のために変更することができます。複数のチャネルを使用し、 [Access Manager](https://www.pubnub.com/docs/security/access-control) を使用して、特定のチャネルの読み取り/書き込みを許可するユーザーを保護することもできます。

C#のコード例については、[devrel@pubnub.com](mailto:devrel@pubnub.com)、またはアプリ開発のスピードアップに役立つ[ドキュメントや](https://www.pubnub.com/docs) [開発者向けリソースを](https://www.pubnub.com/developers/)ご覧ください！

PubNubはどのようにあなたを助けることができますか？
============================

この記事は[PubNub.comに](https://pubnub.com/blog/c-sharp-desktop-notifications-wpf-mvvm/)掲載されたものです。

PubNubのプラットフォームは、開発者がWebアプリ、モバイルアプリ、IoTデバイス向けにリアルタイムのインタラクティブ機能を構築、提供、管理できるように支援します。

私たちのプラットフォームの基盤は、業界最大かつ最もスケーラブルなリアルタイムエッジメッセージングネットワークです。世界15か所以上で8億人の月間アクティブユーザーをサポートし、99.999%の信頼性を誇るため、停電や同時実行数の制限、トラフィックの急増による遅延の問題を心配する必要はありません。

PubNubを体験
---------

[ライブツアーを](https://www.pubnub.com/tour/introduction/)チェックして、5分以内にすべてのPubNub搭載アプリの背後にある本質的な概念を理解する

セットアップ
------

[PubNubアカウントに](https://admin.pubnub.com/signup/)サインアップすると、PubNubキーに無料ですぐにアクセスできます。

始める
---

[PubNubのドキュメントは](https://www.pubnub.com/docs)、ユースケースや[SDKに](https://www.pubnub.com/docs)関係なく、あなたを立ち上げ、実行することができます。