我从web套接字加载了大约190个项目,并在listview中显示它们,但数据更新太慢,与实际数据不同步。我试了一件东西,效果很好。是否有更有效的方法将数据绑定到ObservableCollection上?我应该尝试虚拟化吗?或者有其他的建议,使代码工作预期?这是我的代码
模型:
public class WSFuturesResponse
{
public string channel { get; set; }
public string market { get; set; }
public string type { get; set; }
public WSFuturesData data { get; set; } = new WSFuturesData();
}
public class WSFuturesData
{
public double? bid { get; set; }
public double? ask { get; set; }
public double? bidSize { get; set; }
public double? askSize { get; set; }
public double? last { get; set; }
public double? time { get; set; }
}
public class Tickers
{
public string Market { get; set; }
public double? Price { get; set; }
public Tickers(string market)
{
Market = market;
}
}
public class ApiFuturesData
{
public string name { get; set; }
}
public class ApiFuturesResponse
{
public bool success { get; set; }
public List<ApiFuturesData> result { get; set; }
}
ViewModel
public class Ticker : INotifyPropertyChanged
{
protected string url = "wss://ftx.com/ws/";
protected WebSocket _webSocketClient;
public Action OnWebSocketConnect;
public event PropertyChangedEventHandler PropertyChanged;
private WSFuturesResponse _futuresResponse;
public List<Tickers> ListTickers = new List<Tickers>();
public WSFuturesResponse FuturesResponse
{
get
{
return _futuresResponse;
}
set
{
_futuresResponse = value;
OnPropertyChanged("FuturesResponse");
// Use the dispatcher to avoid System.NotSupportedException
App.Current.Dispatcher.Invoke(delegate
{
Tickers.Clear();
foreach (var future in ListTickers)
{
if (future.Market == FuturesResponse.market)
{
future.Price = FuturesResponse.data.last;
}
Tickers.Add(future);
}
});
}
}
public ObservableCollection<Tickers> Tickers { get; set; }
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public Ticker()
{
Tickers = new ObservableCollection<Tickers>();
StartWebSocket();
}
public void StartWebSocket()
{
Client client = new Client("firstkey", "secondkey");
FtxRestApi api = new FtxRestApi(client);
StartConnection(this, client, api);
}
private async void StartConnection(Ticker wsApi, Client client, FtxRestApi api)
{
// get all futures data from the API
var futures = await api.GetAllFuturesAsync();
// parse the data
ApiFuturesResponse all_futures = JsonConvert.DeserializeObject<ApiFuturesResponse>(futures);
wsApi.OnWebSocketConnect += () =>
{
wsApi.SendCommand(FtxWebSocketRequestGenerator.GetAuthRequest(client));
foreach (ApiFuturesData future in all_futures.result)
{
if (future.name.Contains("PERP"))
{
// add the name to the list and use it to subscribe to the channel
ListTickers.Add(new Tickers(future.name));
wsApi.SendCommand(FtxWebSocketRequestGenerator.GetSubscribeRequest("ticker", future.name));
}
}
};
await wsApi.Connect();
}
public void WebsocketOnMessageReceive(object o, MessageReceivedEventArgs messageReceivedEventArgs)
{
FuturesResponse = JsonConvert.DeserializeObject<WSFuturesResponse>(messageReceivedEventArgs.Message);
}
XAML代码:
<Window x:Class="FTXTradingClient.Views.TickerView"
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:FTXTradingClient.ViewModel"
xmlns:local="clr-namespace:FTXTradingClient.Views"
mc:Ignorable="d"
Title="FTX Trading Client" Height="850" Width="1200">
<Window.Resources>
<vm:Ticker x:Key="vm"/>
</Window.Resources>
<Grid DataContext="{StaticResource vm}">
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="50"/>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<ListView Grid.Row="2"
Grid.Column="1"
ItemsSource="{Binding Tickers}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Market}"/>
<Label Grid.Column="1"/>
<TextBlock Grid.Column="2" Text="{Binding Price}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Window>
您可以尝试重置Tickers
属性,而不是首先清除其中的所有项目,然后添加新的项目:
public WSFuturesResponse FuturesResponse
{
get
{
return _futuresResponse;
}
set
{
_futuresResponse = value;
OnPropertyChanged("FuturesResponse");
foreach (var future in ListTickers)
{
if (future.Market == FuturesResponse.market)
{
future.Price = FuturesResponse.data.last;
}
}
// Use the dispatcher to avoid System.NotSupportedException
App.Current.Dispatcher.Invoke(delegate
{
Tickers = new ObservableCollection<Tickers>(ListTickers);
});
}
}
private ObservableCollection<Tickers> _tickers;
public ObservableCollection<Tickers> Tickers
{
get { return _tickers; }
set { _tickers = value; OnPropertyChanged("Tickers"); }
}