私は非常に奇妙な問題に遭遇しました。
基本的な考え方は、外国為替価格に関する取引 API から受信したデータを保存するクラスがあるということです。各プロパティは、以下のように NotifyPropertyChanged メソッドで設定されています。
class RealTimeBar
{
public event PropertyChangedEventHandler PropertyChanged;
private const double EPSILON = 0.0000001;
private int _id;
private string _symbol;
private int _time;
private float _open;
private float _high;
private float _low;
private float _close;
int _volume;
public RealTimeBar(int id, string symbol)
{
_id = id;
_symbol = symbol;
}
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public int Id
{
get
{
return _id;
}
set
{
_id = value;
}
}
public string Symbol
{
get
{
return _symbol;
}
set
{
if (value != _symbol)
{
_symbol = value;
NotifyPropertyChanged("Symbol");
}
}
}
public int Time
{
get
{
return _time;
}
set
{
if (value != _time)
{
_time = value;
NotifyPropertyChanged("Time");
}
}
}
public float Open
{
get
{
return _open;
}
set
{
if (value != _open)
{
_open = value;
NotifyPropertyChanged("Open");
}
}
}
public float High
{
get
{
return _high;
}
set
{
if (value != _high)
{
_high = value;
NotifyPropertyChanged("High");
}
}
}
public float Low
{
get
{
return _low;
}
set
{
if (value != _low)
{
_low = value;
NotifyPropertyChanged("Low");
}
}
}
public float Close
{
get
{
return _close;
}
set
{
if (value != _close)
{
_close = value;
NotifyPropertyChanged("Close");
}
}
}
public int Volume
{
get
{
return _volume;
}
set
{
if (value != _volume)
{
_volume = value;
NotifyPropertyChanged("Volume");
}
}
}
}
長いクラスを引用していますが、ご覧のとおり単純な構造です。ここで、イベントを発生させるAPIに接続し、定義したクラスにAPIの値を設定して処理します。
BindingList<RealTimeBar> _realTimeBarList = new BindingList<RealTimeBar>();
public Hashtable _iForexHashtable = new Hashtable();
private void _UpdateForexQuote(int tickerId, int time, double open, double high, double low, double close, int volume,
double wap, int count)
{
///MessageBox.Show(tickerId.ToString());
((RealTimeBar)_iForexHashtable[tickerId]).Open = (float)open;
((RealTimeBar)_iForexHashtable[tickerId]).High = (float)high;
((RealTimeBar)_iForexHashtable[tickerId]).Low = (float)low;
((RealTimeBar)_iForexHashtable[tickerId]).Close = (float)close;
((RealTimeBar)_iForexHashtable[tickerId]).Volume = volume;
}
いくつかの設定の後、メソッド _UpdateForexQuote は、来る情報を RealTimeBar クラスのプロパティに配布します。すべて順調。
プログラムを起動しても更新されません。データが入っていないと思っていたのですが、gridcontrol の A1cell のどこかをランダムにクリックしてから別の B1cell をクリックすると、前の A1cell が更新されてしまいます。次に、C1cell をクリックすると、B1cell が更新されます。1 つのセルをクリックしないと、更新されません。私はあなたに写真を見せます:
ご覧のとおり、最初の 3 行をクリックすると、最初の 3 行には遅延データが表示され、4 行目には触れていないため、ゼロが表示されます。条件は、5 行目の Low セルをクリックしたことです。そのため、Low は更新されませんが、他のセルは更新されます。とても奇妙です。以前はvs 2010でdevexpress 11で同じコードを使用していましたが、vs 2012でdevexpress 12を使用すると、以前は発生しなかったこの問題に遭遇しました。
アップデート:
以下は、1.バインディングリストとハッシュテーブルを定義するために使用する方法です。2.最初にオブジェクトをハッシュテーブルに入れ、ハッシュテーブルからバインディングリストにオブジェクトを追加します。
private void earningButtonItem_ItemClick(object sender, ItemClickEventArgs e)
{
_iTimer.AutoReset = false;
_iTimer.Enabled = false;
switchStockPool = "Earning Stock";
disconnectButtonItem.PerformClick();
connectButtonItem.PerformClick();
_iheitanshaoEarningDBConnect = new DBConnect("heitanshaoearning");
List<string>[] tempList;
int tempHash;
tempList = _iheitanshaoEarningDBConnect.SelectSymbolHighLow();
_quoteEarningOnGridList.Clear();
///tempList[0].Count
for (int i = 0; i < tempList[0].Count; i++)
{
tempHash = Convert.ToInt32(tempList[0][i].ToString().GetHashCode());
_iStockEarningHistHashtable[tempHash] = new QuoteOnGridHist(tempList[0][i], (float)Convert.ToSingle(tempList[1][i]), (float)Convert.ToSingle(tempList[2][i]), (float)Convert.ToSingle(tempList[3][i]));
_iStockEarningHashtable[tempHash] = new QuoteOnGrid(tempList[0][i], 0, 0);
_quoteEarningOnGridList.Add((QuoteOnGrid)_iStockEarningHashtable[tempHash]);
reqMktDataExStock(tempHash, tempList[0][i].ToString());
}
List<string>[] tempVolumeList;
tempVolumeList = _iheitanshaoEarningDBConnect.SelectAverageVolume();
for (int i = 0; i < tempList[0].Count; i++)
{
tempHash = Convert.ToInt32(tempVolumeList[0][i].ToString().GetHashCode());
((QuoteOnGrid)_iStockEarningHashtable[tempHash]).Average_Volume = ((float)Convert.ToSingle(tempVolumeList[1][i])) / volumeDenominator;
}
gridControl.DataSource = _quoteEarningOnGridList;
}
/////////////////////
価格更新イベントが来ると、以下のメソッドはハッシュテーブルのオブジェクト プロパティを更新します。オブジェクトに Notifypropertychanged を定義したので、bingdinglist と gridcontrol でオブジェクトを更新する必要があります。
private void _UpdateStockMarketQuote(int tikcerId, int field, double price, int canAutoExecute)
{
////MessageBox.Show(tikcerId.ToString() + field.ToString() + price.ToString());
if (switchStockPool == "Selected Stock")
{
if (field == 4)
{
((QuoteOnGrid)_iStockHashtable[tikcerId]).Gap_From_High = ((float)price - ((QuoteOnGridHist)_iStockHistHashtable[tikcerId]).High) / ((QuoteOnGridHist)_iStockHistHashtable[tikcerId]).Close;
((QuoteOnGrid)_iStockHashtable[tikcerId]).Gap_From_Low = ((float)price - ((QuoteOnGridHist)_iStockHistHashtable[tikcerId]).Low) / ((QuoteOnGridHist)_iStockHistHashtable[tikcerId]).Close;
((QuoteOnGrid)_iStockHashtable[tikcerId]).Last_Price = (float)price;
}
//else if (field == 1)
//{
// ((QuoteOnGrid)_iStockHashtable[tikcerId]).Gap_From_High = ((float)price - ((QuoteOnGridHist)_iStockHistHashtable[tikcerId]).High) / ((QuoteOnGridHist)_iStockHistHashtable[tikcerId]).Close;
// ((QuoteOnGrid)_iStockHashtable[tikcerId]).Gap_From_Low = ((float)price - ((QuoteOnGridHist)_iStockHistHashtable[tikcerId]).Low) / ((QuoteOnGridHist)_iStockHistHashtable[tikcerId]).Close;
//}
}
else if (switchStockPool == "Earning Stock")
{
if (field == 4)
{
((QuoteOnGrid)_iStockEarningHashtable[tikcerId]).Gap_From_High = ((float)price - ((QuoteOnGridHist)_iStockEarningHistHashtable[tikcerId]).High) / ((QuoteOnGridHist)_iStockEarningHistHashtable[tikcerId]).Close;
((QuoteOnGrid)_iStockEarningHashtable[tikcerId]).Gap_From_Low = ((float)price - ((QuoteOnGridHist)_iStockEarningHistHashtable[tikcerId]).Low) / ((QuoteOnGridHist)_iStockEarningHistHashtable[tikcerId]).Close;
((QuoteOnGrid)_iStockEarningHashtable[tikcerId]).Last_Price = (float)price;
}
//else if (field == 1)
//{
// ((quoteongrid)_istockearninghashtable[tikcerid]).gap_from_high = ((float)price - ((quoteongridhist)_istockearninghisthashtable[tikcerid]).high) / ((quoteongridhist)_istockearninghisthashtable[tikcerid]).close;
// ((quoteongrid)_istockearninghashtable[tikcerid]).gap_from_low = ((float)price - ((quoteongridhist)_istockearninghisthashtable[tikcerid]).low) / ((quoteongridhist)_istockearninghisthashtable[tikcerid]).close;
//}
}
}