簡體   English   中英

C# Blazor 服務器:使用 INotifyPropertyChanged 顯示實時數據

[英]C# Blazor Server: Display live data using INotifyPropertyChanged

我有一個小問題,我嘗試在我的 Blazor 服務器項目的頁面上顯示實時數據。 在閱讀了幾篇文章后,我認為使用 INotifyPropertyChanged 應該可以做到這一點。 不幸的是,我對此很陌生,這是我嘗試過的:

我的 Model 價格與 INotifyPropertyChanged(使用 Rider 生成):

public class Price : INotifyPropertyChanged
{
    private double _askPrice;
    private double _bidPrice;
    private double _spread;

    public Price(double askPrice, double bidPrice)
    {
        _askPrice = askPrice;
        _bidPrice = bidPrice;
    }

    public double AskPrice {
        get => _askPrice;
        set
        {
            _askPrice = value; 
            OnPropertyChanged("AskPrice");
            OnPropertyChanged("Spread");
        }
    }

    public double BidPrice
    {
        get => _bidPrice;
        set
        {
            _bidPrice = value; 
            OnPropertyChanged("BidPrice");
            OnPropertyChanged("Spread");
        }
    }

    public double Spread => _askPrice - _bidPrice;

    public event PropertyChangedEventHandler PropertyChanged;
    
    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

我如何獲取實時數據:

public class PriceService
{
    public static Price BinancePrice;

    public static void StartBinanceStream()
    {
        var client = new BinanceSocketClient();
        // subscribe to updates on the spot API
        client.Spot.SubscribeToBookTickerUpdates("BTCEUR", data =>
        {
            BinancePrice = new Price((double)data.BestAskPrice, (double)data.BestBidPrice);
        });
    }
}

最后是我的剃刀文件的內容:

<h5>BID: @($"{PriceService.BinancePrice.BidPrice:F2} EUR")</h5>
<h5>ASK: @($"{PriceService.BinancePrice.AskPrice:F2} EUR")</h5>
<h5>Spread: @($"{PriceService.BinancePrice.Spread:F2} EUR")</h5>

@code {
protected override async Task OnInitializedAsync()
{
    PriceService.BinancePrice.PropertyChanged += async (sender, e) => { await InvokeAsync(StateHasChanged); };
    await base.OnInitializedAsync();
}

async void OnPropertyChangedHandler(object sender, PropertyChangedEventArgs e)
{
    await InvokeAsync(StateHasChanged);
}

public void Dispose()
{
    PriceService.BinancePrice.PropertyChanged -= OnPropertyChangedHandler;
}
}

它確實顯示了數據,但沒有實時顯示更改,我需要重新打開選項卡或刷新頁面以查看當前數據。 目標是每次價格變化時 UI 都會刷新。 如果你能幫我解決這個問題會很棒::)

我無法真正驗證問題的根源,盡管在我看來它與 Price class 和 PropertyChangedEventHandler 的調用有關

但是,這里的代碼示例應該可以工作:

價格.cs

public class Price : INotifyPropertyChanged
{
    private double _askPrice;
    private double _bidPrice;
    private double _spread;

    public Price(double askPrice, double bidPrice)
    {
        _askPrice = askPrice;
        _bidPrice = bidPrice;
    }

    public double AskPrice
    {
        get => _askPrice;
        set => SetProperty(ref _askPrice, value);
    }

    public double BidPrice
    {
        get => _bidPrice;
        set => SetProperty(ref _bidPrice, value);
    }

    public double Spread => _askPrice - _bidPrice;

    public event PropertyChangedEventHandler PropertyChanged;

    void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new 
                         PropertyChangedEventArgs(propertyName));
    }

    bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string 
                                                     propertyName = null)
    {
        if (Equals(storage, value))
        {
            return false;
        }

        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }
 } 

PriceService.cs

 public class PriceService
 {
    public Price BinancePrice { get; set; }
    double count;
    double BestAskPrice;
    double BestBidPrice;
    public PriceService()
    {
        BlazorTimer t = new BlazorTimer();
        t.SetTimer(3000, 1, 100);
        t.CountCompleted += NotifyCompleted;
        BestAskPrice = 102.09;
        BestBidPrice = 101.03;
        BinancePrice = new Price((double)BestAskPrice, (double)BestBidPrice);

    }

    private void NotifyCompleted(object sender, TimerEventArgs args)
    {
        count = (double) args.Count;

        BestAskPrice += count;
        BestBidPrice += count;
        BinancePrice.AskPrice = (double)BestAskPrice;
        BinancePrice.BidPrice =  (double)BestBidPrice;
    }
 }

注意:PriceService 是一項服務,應該添加到 DI Container 中:

services.AddSingleton<PriceService>();

另請注意,我避免使用 static 東西。 注意:為了驗證 UI 是否在發生變化,我使用了 Timer。 它真的很粗糙,你只需要使用它來查看事情是否正常,然后應用你的代碼......

BlazorTimer.cs

public class BlazorTimer
{
    private Timer _timer;
    private int count;
    private int end;
    internal void SetTimer(double interval, int start, int _end)
    {
        _timer = new Timer(interval);
        _timer.Elapsed += Counter;
        _timer.Enabled = true;
        count = start;
        end = _end;
        _timer.Start();
    }

     
    private void Counter(object sender, ElapsedEventArgs e)
    {
        count++;
        TimerEventArgs args = new TimerEventArgs { Count = count };
        OnCountCompleted(args);
      
    }
       
    protected virtual void OnCountCompleted(TimerEventArgs args)
    {
        EventHandler<TimerEventArgs> handler = CountCompleted;
        if (handler != null)
        {
            handler(this, args);
        }
    }

    public event EventHandler<TimerEventArgs> CountCompleted;
 }

 public class TimerEventArgs : EventArgs
 {
    public int Count { get; set; }
 } 

用法

@*@implements IDisposable*@
    
@inject PriceService PriceService

<h5>BID: @($"{PriceService.BinancePrice.BidPrice:F2} EUR")</h5>
<h5>ASK: @($"{PriceService.BinancePrice.AskPrice:F2} EUR")</h5>
<h5>Spread: @($"{PriceService.BinancePrice.Spread:F2} EUR")</h5>

@code {
    protected override async Task OnInitializedAsync()
    {
        PriceService.BinancePrice.PropertyChanged += async (sender, e) => { await InvokeAsync(StateHasChanged); };
        await base.OnInitializedAsync();
    }

    //async void OnPropertyChangedHandler(object sender, PropertyChangedEventArgs e)
    //{
    //    await InvokeAsync(StateHasChanged);
    //}

    //public void Dispose()
    //{
    //    PriceService.BinancePrice.PropertyChanged -= OnPropertyChangedHandler;
    //}
}   

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM