FlexGrid for WinForms
FinancialData
    
        public class FinancialData : INotifyPropertyChanged
    {
        const int HISTORY_SIZE = 5;
        List<decimal> _askHistory = new List<decimal>();
        List<decimal> _bidHistory = new List<decimal>();
        List<decimal> _saleHistory = new List<decimal>();

       
        public string Symbol
        {
            get { return (string)GetProp("Symbol",typeof(string)); }
            set { SetProp("Symbol", value); }
        }

        public string Name
        {
            get { return (string)GetProp("Name", typeof(string)); }
            set { SetProp("Name", value); }
        }

      
        public decimal Bid
        {
            get { return (decimal)GetProp("Bid", typeof(decimal)); }
            set 
            {
                AddHistory(_bidHistory, value);
                SetProp("Bid", value);
            }
        }

        
        public decimal Ask
        {
            get { return (decimal)GetProp("Ask", typeof(decimal)); }
            set 
            {
                AddHistory(_askHistory, value);
                SetProp("Ask", value);
            }
        }

   
        public decimal LastSale
        {
            get { return (decimal)GetProp("LastSale", typeof(decimal)); }
            set 
            {
                AddHistory(_saleHistory, value);
                SetProp("LastSale", value);
            }
        }

        public int BidSize
        {
            get { return (int)GetProp("BidSize", typeof(int)); }
            set { SetProp("BidSize", value); }
        }

        public int AskSize
        {
            get { return (int)GetProp("AskSize", typeof(int)); }
            set { SetProp("AskSize", value); }
        }

        public int LastSize
        {
            get { return (int)GetProp("LastSize", typeof(int)); }
            set { SetProp("LastSize", value); }
        }

  
        public int Volume
        {
            get { return (int)GetProp("Volume", typeof(int)); }
            set { SetProp("Volume", value); }
        }

        public DateTime QuoteTime
        {
            get { return (DateTime)GetProp("QuoteTime", typeof(DateTime)); }
            set { SetProp("QuoteTime", value); }
        }

       
        public DateTime TradeTime
        {
            get { return (DateTime)GetProp("TradeTime", typeof(DateTime)); }
            set { SetProp("TradeTime", value); }
        }

        public List<decimal> AskHistory
        {
            get { return GetHistory("Ask"); }
        }

        public List<decimal> BidHistory {
            get
            {
                return GetHistory("Bid");
            }
            }
        public List<decimal> LastSaleHistory {
            get
            {
                return GetHistory("LastSale");
            }
            }
        public List<decimal> GetHistory(string propName)
        {
            switch (propName)
            {
                case "Ask":
                    return _askHistory;
                case "Bid":
                    return _bidHistory;
                case "LastSale":
                    return _saleHistory;
            }
            return null;
        }
        void AddHistory(List<decimal> list, decimal value)
        {
            while (list.Count >= HISTORY_SIZE)
            {
                list.RemoveAt(0);
            }
            while (list.Count < HISTORY_SIZE)
            {
                list.Add(value);
            }
        }

        Dictionary<string, object> _propBag = new Dictionary<string, object>();
        object GetProp(string propName,Type type)
        {
            object value = null;
            _propBag.TryGetValue(propName, out value);
            //プロパティの get でキャストするときに NullReferenceException を回避するために、null 値を処理します。
            if (value is null && type.IsValueType) {
                return Activator.CreateInstance(type);
            }
            return value;
        }
        void SetProp(string propName, object value)
        {
            if (!_propBag.ContainsKey(propName) || GetProp(propName,typeof(object)) != value)
            {
                _propBag[propName] = value;
                OnPropertyChanged(new PropertyChangedEventArgs(propName));
                //対応する履歴プロパティの PropertyChanged を起動します。
                switch (propName)
                {
                    case "Ask":
                        OnPropertyChanged(new PropertyChangedEventArgs("AskHistory"));
                        return;
                    case "Bid":
                        OnPropertyChanged(new PropertyChangedEventArgs("BidHistory"));
                        return;
                    case "LastSale":
                        OnPropertyChanged(new PropertyChangedEventArgs("LastSaleHistory"));
                        return;
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, e);
        }

        // 財務項目のデフォルト リストを取得します。
        public static FinancialDataList GetFinancialData()
        {
            var list = new FinancialDataList();
            var rnd = new Random(0);
            var asm = Assembly.GetExecutingAssembly();
            foreach (string resName in asm.GetManifestResourceNames())
            {
                if (resName.EndsWith("data.zip"))
                {
                    var zip = new C1.C1Zip.C1ZipFile(asm.GetManifestResourceStream(resName));
                    using (var sr = new StreamReader(zip.Entries["StockSymbols.txt"].OpenReader()))
                    {
                        while (!sr.EndOfStream)
                        {
                            var sn = sr.ReadLine().Split('\t');
                            if (sn.Length > 1 && sn[0].Trim().Length > 0)
                            {
                                var data = new FinancialData();
                                data.Symbol = sn[0];
                                data.Name = sn[1];
                                data.Bid = rnd.Next(1, 1000);
                                data.Ask = data.Bid + (decimal)rnd.NextDouble();
                                data.LastSale = data.Bid;
                                data.BidSize = rnd.Next(10, 500);
                                data.AskSize = rnd.Next(10, 500);
                                data.LastSize = rnd.Next(10, 500);
                                data.Volume = rnd.Next(10000, 20000);
                                data.QuoteTime = DateTime.Now;
                                data.TradeTime = DateTime.Now;
                                list.Add(data);
                            }
                        }
                    }
                    list.AutoUpdate = true;
                    return list;
                }
            }
            throw new Exception("Can't find 'data.zip' embedded resource.");
        }
    }