Powiadomienia Toast w C#, WPF i MVVM
Published: 2023-12-01 11:54:21

Czy zauważyłeś, że [powiadomienia](https://www.pubnub.com/use-case/alerts-and-push-notifications/) na pulpicie stały się niezbędną funkcją w aplikacjach działających w czasie rzeczywistym, opartych [na zdarzeniach](https://www.pubnub.com/guides/event-driven-architecture/). Usługi sieciowe muszą powiadamiać użytkowników o sygnałach z zaplecza lub wiadomościach od innych użytkowników w miarę ich występowania.

Jeśli jesteś inżynierem oprogramowania lub programistą full-stack, który chce zbudować aplikację Windows Desktop przy użyciu **C#** i **WPF**, **Windows Forms** lub **UWP**, ten przewodnik przeprowadzi Cię przez tworzenie **kodu front-end i back-end** dla powiadomień push na pulpicie przy użyciu **wzorca projektowego MVVM**.

Główną rolę odgrywa tutaj interfejs[**API**](https://www.pubnub.com/docs/channels/overview) **PubNub** do[**przesyłania wiadomości w czasie rzeczywistym**](https://www.pubnub.com/docs/channels/overview), który umożliwia klientom lub serwerom wysyłanie sygnałów w czasie rzeczywistym do dowolnej liczby urządzeń, aplikacji internetowych i aplikacji mobilnych z dowolnego miejsca na świecie.

**Przegląd języków programowania potrzebnych do obsługi powiadomień toastowych**
--------------------------------------------------------------------------------

W tym samouczku będziemy używać różnych języków kodowania i algorytmów. Na początek podamy krótką definicję tych języków programowania, a następnie zagłębimy się w proces przepływu pracy.

**Czym jest WPF?**
------------------

Przykład kodu, który zamierzamy wspólnie przeanalizować, został napisany przy użyciu [Windows Presentation Foundation](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/getting-started/introduction-to-wpf-in-vs?view=netframeworkdesktop-4.8) lub WPF. Przez ostatnią dekadę WPF był najlepszym podsystemem do tworzenia aplikacji internetowych Windows Desktop z **C# i .NET Framework**. Przypomina Windows Forms z wykorzystaniem [XAML](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/fundamentals/xaml?view=netdesktop-5.0) do tworzenia interfejsu użytkownika i C# [Code Behinds](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/advanced/code-behind-and-xaml-in-wpf?view=netframeworkdesktop-4.8) dla każdego widoku.

**Szybka wskazówka:**

W tym samouczku zamierzamy zachować jak najwięcej kodu poza Code Behind, ponieważ będziemy używać wzorca MVVM. Z tego powodu kod, który normalnie pojawiłby się w klasach Code Behind, **zostanie zamiast tego umieszczony w klasach ViewModel**.

**Czym jest architektura MVVM?**
--------------------------------

**Model-View-ViewModel** lub MVVM to wzorzec projektowy służący do **oddzielenia** rozwoju interfejsu użytkownika od rozwoju zaplecza w aplikacji skierowanej do użytkownika. Istnieją **trzy komponenty**, które składają się na ten wzorzec.

### Jakie są komponenty WPFApps?

W przypadku WPFapps są to następujące komponenty:

-   Widoki - [XAML i CodeBehinds](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/advanced/code-behind-and-xaml-in-wpf?view=netframeworkdesktop-4.8)
    
-   ViewModels - kod C# do zarządzania stanem i kontrolowania danych, które przemieszczają się między modelem a widokiem.
    
-   Modele - klasy C#, przechowywanie danych, logika biznesowa.
    

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

**Powiadomienia pulpitu w języku C#**
-------------------------------------

Rozwiązaniem Windows Desktop dla powiadomień uwzględniających system operacyjny jest klasa Toast **Notification**. Powiadomienia Toast są zintegrowane z klasą Windows UI Notification.

### Czym jest powiadomienie Toast?

W tym przykładzie użyjemy powiadomienia Toast. Powiadomienie Toast to małe wyskakujące okienko, które jest zaprogramowane tak, aby pojawiało się i wygasało automatycznie. Zazwyczaj nie rzuca się w oczy i nie wymaga żadnych działań ze strony użytkownika. Nie zatrzymuje również aktywności użytkownika.

Ten typ automatycznych powiadomień push jest idealny dla wyskakujących okienek na pulpicie. Jednak wsparcie dla Toast w WPF nie jest obfite.

#### **Wskazówka pro powiadomienia Toast:**

Obejściem dla tego scenariusza jest zbudowanie własnego interfejsu użytkownika powiadomień na pulpicie, aby aplikacja WPF mogła zawierać powiadomienia. Takie powiadomienie może zostać **uruchomione w dowolnym momencie** za pomocą konwencjonalnego zdarzenia C# w kodzie ViewModel.

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

Przykład, który wspólnie zbudujemy, to aplikacja WPFapp z powiadomieniami C#.

Będzie **jedno okno nadrzędne** z jednym przyciskiem. Kliknięcie przycisku wywoła PubNub [publikujący](https://www.pubnub.com/docs/sdks/c-sharp/) **dane JSON** do sieci. Aplikacja będzie również **subskrybować** PubNub przy użyciu **tego samego kanału i kluczy API**, co kod publikowania (bezpłatne [klucze PubNubAPI](https://dashboard.pubnub.com/signup)).

Kod subskrypcji PubNub wywoła **zdarzenie C#**, które utworzy wyskakujące powiadomienie push na pulpicie za każdym razem, gdy zostanie opublikowana nowa wiadomość. Opóźnienie dla wiadomości PubNub wynosi **zazwyczaj od 80 do 100 milisekund**, niezależnie od odległości wydawcy i subskrybenta.

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

PubNub posiada ponad **70 klienckich** [**zestawów SDK**](https://www.pubnub.com/docs/sdks), więc każde urządzenie z dostępem do Internetu może zostać włączone do tego schematu.

Projekt samouczka powiadomień WPFTutorial z C# i MVVM
-----------------------------------------------------

Zamierzamy zbudować własną aplikację powiadomień w języku C#, aby zademonstrować moc komunikatów PubNub i rozwiązanie dla powiadomień pulpitu WPF. Oto struktura plików projektu MVVM:

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

_Cały kod, do którego odwołuje się ten poradnik_ , jest dostępny jako**_open source w serwisie_** [**_GitHub_**](https://github.com/ajb413/wpf-pubnub-desktop-notifications)_._

Aby uruchomić_aplikację_ , należy uzyskać**_na zawsze bezpłatne_**[**_klucze PubNubAPI_**](https://dashboard.pubnub.com/signup)_._

Pamiętaj, aby dodać klucze **Publish i Subscribe** do kodu źródłowego!

**Tworzenie powiadomienia na pulpicie zaczynając od MVVM**
----------------------------------------------------------

1\. Jeśli zaczynasz od zera, otwórz Visual**Studio**[(za darmo](https://visualstudio.microsoft.com/vs/community/)) i utwórz nową aplikację **WPFweb**. Kliknij **Plik -> Nowy -> Projekt**.

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

2\. Kliknij prawym przyciskiem myszy plik nowego projektu w **Solution Explorer** i kliknij **Manage NuGet Packages**. Aby kontynuować, musimy zainstalować **PubNub**.

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

3\. Utwórz foldery w **katalogu głównym** projektu, jak pokazano na wcześniejszym **zrzucie** ekranu. Te foldery to **Model, View i ViewModel**. W folderze View utwórz 2 nowe okna XAML, **Main Window** i **Notification Window**.

**Kontynuacja tworzenia powiadomień za pomocą XAML**
----------------------------------------------------

Oto XAML dla 2 utworzonych plików widoku. Stworzy to **interfejs użytkownika** naszego okna nadrzędnego i okna powiadomień.

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="{Binding ButtonContent}" Background="#FFF3F0F0"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <ei:CallMethodAction TargetObject="{Binding}" MethodName="PublishMessage"/> </i:EventTrigger> </i:Interaction.Triggers> </Button> </Border> </StackPanel> </Grid> </Window>.

**NotificationWindow.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> <!-- Obszar powiadomień --> <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" Click="Button\_Click\_Close" VerticalAlignment="Top" Background="{x:Null}" Width="42" Height="43"> <Image Source="CloseBtn.JPG" Height="39" Width="28" /> </Button> </Grid> </Window>

### Przykład kodu okna powiadomień w języku C#

Poniżej znajduje się kod **C#** dla okna [powiadomień](https://github.com/ajb413/wpf-pubnub-desktop-notifications/blob/master/WPF_PubNub/View/NotificationWindow.xaml.cs). Cały kod jest specyficzny dla interfejsu użytkownika. Ma on przypominać powiadomienie "Toast".

using System; using System.Windows; using System.Windows.Threading; namespace Toast { /// <summary> /// Logika interakcji dla NotificationWindow.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(); } } }

**Ostatni krok do stworzenia powiadomienia w C#, WPF i MVVM**
-------------------------------------------------------------

1.  W folderze ViewModel utwórz klasę **PubNubVM.cs**, która będzie pośrednikiem między **kodem modelu** a **kodem widoku**. Kod tego pliku można znaleźć [tutaj](https://github.com/ajb413/wpf-pubnub-desktop-notifications/blob/master/WPF_PubNub/ViewModel/PubNubVM.cs).
    
2.  W folderze Model utwórz klasę **PubNubHelper.** cs do interakcji z PubNub publish/subscribe API. Pamiętaj, **aby wprowadzić własne** [**klucze PubNubAPI**](https://dashboard.pubnub.com/signup) **w kodzie inicjalizacyjnym PubNub**.
    
3.  Możesz zobaczyć "\_\_YOUR\_PUBNUB\_PUBLISH\_KEY\_HERE\_\_" i "\_\_YOUR\_PUBNUB\_SUBSCRIBE\_KEY\_HERE\_\_" w pliku. Zastąp te literały łańcuchowe swoimi kluczami.
    

using Newtonsoft.Json; using PubnubApi; using System; using System.Windows; using Toast; namespace WPF\_PubNub.Model { public class PubNubHelper { Pubnub pubnub; private readonly string ChannelName = "win-notification";
        public void Init() { //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(); } //Publish a message public void Publish() { JsonMsg Person = new JsonMsg { Name = "John Doe", Description = "Description", Date = DateTime.Now.ToString() }; //Convert to string string arrayMessage = JsonConvert.SerializeObject(Person); pubnub.Publish() .Channel(ChannelName) .Message(arrayMessage) .Async(new PNPublishResultExt((result, status) => {})); } //listen to the channel public void Listen() { SubscribeCallbackExt listenerSubscribeCallack = new SubscribeCallbackExt( (pubnubObj, message) => { //Call the notification windows from the UI thread Application.Current.Dispatcher.Invoke(new Action() => { //Show the message as a WPF window message like WIN-10 toast NotificationWindow ts = new NotificationWindow(); //Convert the message to JSON JsonMsg bsObj = JsonConvert.DeserializeObject<JsonMsg>(message.Message.ToString()); string messageBoxText = "Name: " + bsObj.Name + Environment.NewLine + "Description: " + bsObj.Description + Environment.NewLine + "Date: " + bsObj.Date; ts.NotifText.Text = messageBoxText; ts.Show(); })); }, (pubnubObj, presence) => { // obsługuj przychodzące dane obecności }, (pubnubObj, status) => { // zwracany obiekt statusu jest zawsze związany z subskrypcją, ale może zawierać // informacje o subskrypcji, bicie serca lub błędy // użyj PNOperationType, aby włączyć różne opcje }); pubnub.AddListener(listenerSubscribeCallack); } } }

**Pro Tip: W folderze Model potrzebna będzie również klasa JsonMsg.cs, którą** można znaleźć[**tutaj**](https://github.com/ajb413/wpf-pubnub-desktop-notifications/blob/master/WPF_PubNub/Model/JsonMsg.cs)**.** Pamiętaj, aby dodać **wszystkie pakiety NuGet, do których odwołuje się** [**plik projektu WPF**](https://github.com/ajb413/wpf-pubnub-desktop-notifications/blob/master/WPF_PubNub/WPF_PubNub.csproj)**.** **Istnieje również kilka plików graficznych JPG dla** [**folderu View**](https://github.com/ajb413/wpf-pubnub-desktop-notifications/tree/master/WPF_PubNub/View)**. Obrazy te pojawiają się w niestandardowym oknie powiadomień. Pamiętaj, aby dodać je do folderu View projektu.**

4\. Uruchom projekt! Kliknij przycisk "Trigger Notification Window". W prawym dolnym rogu pulpitu pojawi się niestandardowe powiadomienie! Jest to obsługiwane przez PubNub, więc jeśli ta aplikacja działa na wielu komputerach, powiadomienie pojawi się na każdym komputerze, dla każdego kliknięcia przycisku.

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

Dzięki wykorzystaniu innych [PubNubSDK](https://www.pubnub.com/docs/sdks) i urządzeń klienckich, system powiadomień jest niezależny od języka/urządzenia.

### **Pierwsze kroki z powiadomieniami Desktop Toast**

Ten wzorzec powiadomień na pulpicie można zmodyfikować w celu uzyskania niestandardowych powiadomień push mających na celu poprawę komfortu użytkowania. Można to osiągnąć za pomocą wielu kanałów, a także za pomocą [Menedżera dostępu](https://www.pubnub.com/docs/security/access-control), aby zabezpieczyć, kto może odczytywać/zapisywać na określonych kanałach.

Aby uzyskać więcej przykładów kodu C#, skontaktuj się z [devrel@pubnub.com](mailto:devrel@pubnub.com) lub zapoznaj się z naszą [dokumentacją](https://www.pubnub.com/docs) i [zasobami dla programistów](https://www.pubnub.com/developers/), aby przyspieszyć tworzenie aplikacji!

Jak PubNub może ci pomóc?
=========================

Ten artykuł został pierwotnie opublikowany na [PubNub.com](https://pubnub.com/blog/c-sharp-desktop-notifications-wpf-mvvm/)

Nasza platforma pomaga programistom tworzyć, dostarczać i zarządzać interaktywnością w czasie rzeczywistym dla aplikacji internetowych, aplikacji mobilnych i urządzeń IoT.

Podstawą naszej platformy jest największa w branży i najbardziej skalowalna sieć komunikacyjna w czasie rzeczywistym. Dzięki ponad 15 punktom obecności na całym świecie obsługującym 800 milionów aktywnych użytkowników miesięcznie i niezawodności na poziomie 99,999%, nigdy nie będziesz musiał martwić się o przestoje, limity współbieżności lub jakiekolwiek opóźnienia spowodowane skokami ruchu.

Poznaj PubNub
-------------

Sprawdź [Live Tour](https://www.pubnub.com/tour/introduction/), aby zrozumieć podstawowe koncepcje każdej aplikacji opartej na PubNub w mniej niż 5 minut.

Rozpocznij konfigurację
-----------------------

Załóż [konto](https://admin.pubnub.com/signup/) PubNub, aby uzyskać natychmiastowy i bezpłatny dostęp do kluczy PubNub.

Rozpocznij
----------

[Dokumenty](https://www.pubnub.com/docs) PubNub pozwolą Ci rozpocząć pracę, niezależnie od przypadku użycia lub [zestawu SDK](https://www.pubnub.com/docs).