web-dev-qa-db-fra.com

Comment actualiser la page Web après la mise à jour de la base de données dans ASP.NET CORE avec Blazor

Je crée une petite application Web de réservation de salle et j'aimerais que la page Web soit actualisée à un intervalle donné; c'est-à-dire une minute donnée ou lorsqu'une modification a été apportée à la base de données. J'ai trouvé StateHasChanged(); mais je ne sais pas vraiment comment l'implémenter (Newbie One Kenobi ici!) J'ai essayé de le mettre dans la fonction pour ajouter un rendez-vous au planning:

var result = Service.CreateSchedule(nextSchedule);
    if (result)
    {
        StateHasChanged();
        NavigationManager.NavigateTo("/roomzfront/1");
    }

Mais j'ai probablement besoin de quelque chose de plus que cela, ou dans un autre endroit du code.

2
Nicolas Lewentorp

Vous pouvez essayer ci-dessous -

<ul>
    @foreach (var booking in Bookings)
    {
        <li>@booking.BookedRoomNumber</li>
    }
</ul>

@functions{

var timer = new Timer(new TimerCallback(_ =>
        {
            // Code to fetch the data and bind it to the page level variable
            // Ex : Bookings = GetBookingsData();

            // This line is necessary
            this.StateHasChanged();
        }), null, 1000, 1000);

}
0
Ritesh Kulkarni

Voici une autre approche si vous ne souhaitez pas utiliser SignalR ou WebSockets.

J'ai un Timer qui distribue sur un intervalle dans le cadre de mon composant Sprite, pour vous donner un exemple de la façon de le faire:

Le Sprite a une propriété appelée Subscriber

[Parameter]
public ISpriteSubscriber { get; set; }

Le composant ou la page Host est une interface ISpriteSubscriber.

namespace DataJuggler.Blazor.Components.Interfaces
{

    #region interface ISpriteSubscriber
    /// <summary>
    /// This interface is used by the AnimationManager to notifiy callers that a refresh occurred.
    /// </summary>
    public interface ISpriteSubscriber
    {

        #region Methods

            #region Refresh()
            /// <summary>
            /// This method will call StateHasChanged to refresh the UI
            /// </summary>
            void Refresh();
            #endregion

            #region Register(Sprite sprite)
            /// <summary>
            /// This method is called by the Sprite to a subscriber so it can register with the subscriber, and 
            /// receiver events after that.
            /// </summary>
            void Register(Sprite sprite);

        #endregion

        #endregion

        #region Properties

            #region ProgressBar
            /// <summary>
            /// This is used so the ProgressBar is stored and available to the Subscriber after Registering
            /// </summary>
            ProgressBar ProgressBar { get; set; }
            #endregion

        #endregion

    }
    #endregion

}

Que dans votre code de rasoir pour définir le parent, vous définissez Subscriber = this:

Sprite Properties

Notez l'intervalle = 50. Cela définit le minuteur pour qu'il s'actualise toutes les 50 millisecondes.

Dans le setter de mon composant Sprite, la première chose que je fais est d'appeler Register avec le parent:

[Parameter]
public ISpriteSubscriber Subscriber
{
    get { return subscriber; }
    set 
    {   
        // set the value
        subscriber = value;

        // if the value for HasSubscriber is true
        if (HasSubscriber)
        {
            // Register with the Subscriber so they can talk to each other
            Subscriber.Register(this);
        }
    }
}

Ce code se trouve ici sur la page d'index qui héberge le sprite et enregistre le sprite avec le parent:

public void Register(Sprite sprite)
{
    // If the Sprite object exists
    if (NullHelper.Exists(Sprite))
    {
        // if this is the RedCar
        if (Sprite.Name == "RedCar")
        {
            // Set the RedCar
            RedCar = Sprite;
        }
        else 
        {
            // Set the WhiteCar
            WhiteCar = Sprite;
        }
    }
}

Maintenant, lorsque mon bouton de départ de course est cliqué, je ne démarre qu'un seul chronomètre, je ne voulais pas que deux chronomètres fonctionnent même si j'ai deux voitures:

public void StartRace()
{
    // if both cars exist
    if (NullHelper.Exists(RedCar, WhiteCar))
    {
        // Create a new instance of a 'RandomShuffler' object.
        Shuffler = new RandomShuffler(2, 12, 100, 3);

        // Start the timer on the RedCar
        RedCar.Start();
    }
}

Voici la méthode Start du Sprite:

public void Start()
{
    this.Timer = new Timer();
    this.Timer.Interval = this.interval;
    this.Timer.Elapsed += Timer_Elapsed;
    this.Timer.Start();
}

Et puis l'événement Timer_Elapsed, appelle l'abonné à actualiser:

private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
    // if a subscriber exists
    if (HasSubscriber)
    {
       // Notify Subscriber
       Subscriber.Refresh();
    }
}

Maintenant, ma méthode d'actualisation est appelée toutes les 50 millisecondes dans ce cas, et je mets à jour mon interface utilisateur:

public void Refresh()
{
    // do your updates

    // Update the UI
    InvokeAsync(() =>
    {
        StateHasChanged();
    });
}

Si vous voulez voir un exemple fonctionnel complet, clonez ce projet et recherchez dans le dossier des exemples le ProgressBarSample.

https://github.com/DataJuggler/DataJuggler.Blazor.Components

Il y a aussi une vidéo ici si vous voulez regarder: https://youtu.be/frtetHgfdIo

J'ai utilisé cette approche parent/enfant pour plusieurs choses et cela a si bien fonctionné que j'ai écrit un article de blog à ce sujet: tilisation d'interfaces pour communiquer entre les composants Blazor

Je trouve que c'est un bon moyen de parler à d'autres composants ou d'envoyer des données.

0
Data Juggler