[英]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 的調用有關
但是,這里的代碼示例應該可以工作:
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;
}
}
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。 它真的很粗糙,你只需要使用它來查看事情是否正常,然后應用你的代碼......
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.