通常のWindows FormsのTreeViewには、DataSourceを利用したデータバインディングがありませんがDevExpressの方の
TreeListにはDataSourceプロパティがあります。なので、よくDataSourceを指定したデータバインディングを行う事が
多いのですが、このときに指定するオブジェクトにはちょっととしたTipsがあります。
何かというと、DataSourceに指定するオブジェクトがDataTableもしくはDataSetの場合、このTreeList、何故かしらないですが
遅くなります。で、BindingSource経由で指定するととても速いです。
尚、この速度差は大量のデータを含んだデータソースの場合に発生します。(たとえば2万件とか)
100件とか200件の場合は気にならない程度の差です。
どれくらいの速度差が出るかというと、私の環境(Intel Xeon 2GHz, 4G RAM)の場合で以下のような感じです。
[2万レコード存在するデータセットを指定した場合のデータバインディングに掛かった時間]
DataSetを直接指定 : 約5.6秒 BindingSourceを指定: 約0.03秒
マシンによって差があると思いますが、大体同じような差が出ると思います。
なので、結論としては
TreeListにてBoundModeで利用する際はBindingSourceをデータソースとして指定する事。
となります。
んで、確認用に作ったサンプルもったいないのであげときます。
必要なDLLはEXEと同じディレクトリにおいてあるのでDevExpressが入っていないマシンでも
動作するはずです。尚、データベース接続も使ってません。
アプリが起動したら、件数を入力して"Create Test Data"ボタンを押下して、その後Reloadボタンを
押下してみてください。各種の読み込みに掛かった時間が表示されます。
DataSetを直接指定した場合のTreeListについては、すごく時間が掛かる場合があるのでデフォルト
でEnabled=falseにしてます。チェックボックスをONにすると計測されるようになります。
フォームのソースコードはこんな感じ。
using System; using System.Data; using System.Diagnostics; using System.Windows.Forms; namespace Gsf.Demo { public partial class MainForm : DevExpress.XtraEditors.XtraForm { public MainForm() { InitializeComponent(); } private void MainForm_Load(object sender, EventArgs e) { txtOutputDataCount.Text = "200"; StartPosition = FormStartPosition.CenterScreen; ActiveControl = txtOutputDataCount; } private void btnCreateTestData_Click(object sender, EventArgs e) { Enabled = false; Application.DoEvents(); if(cmpValidationProvider.Validate()){ DataSet ds = new DataSet("Persons"); DataTable table = ds.Tables.Add(); table.TableName = "Person"; table.Columns.Add("Id", typeof(int)); table.Columns.Add("Name"); table.Columns.Add("Age", typeof(int)); table.Columns.Add("Address"); for (int i = 0; i < int.Parse(txtOutputDataCount.Text); i++) { DataRow r = table.NewRow(); r.ItemArray = new object[] { i, "gsf_zero" + i.ToString(), 28 + i, "address" + i.ToString() }; table.Rows.Add(r); } ds.WriteXml("TestData.xml"); sttMainStatus.Caption = "Data Created."; } Enabled = true; } private void chkEnableTree1_CheckedChanged(object sender, EventArgs e) { trlPersons.Enabled = chkEnableTree1.Checked; } private void btnReload_Click(object sender, EventArgs e) { ReloadData(); } protected void ReloadData() { Stopwatch formLoadingWatch = new Stopwatch(); formLoadingWatch.Reset(); formLoadingWatch.Start(); Stopwatch w = new Stopwatch(); w.Start(); DataSet ds = new DataSet(); ds.ReadXml("TestData.xml"); w.Stop(); lblLoadDataSet.Text = string.Format("Data Set Loading={0}", w.Elapsed.ToString()); lblDataCount.Text = string.Format("Data Count={0}", ds.Tables[0].Rows.Count); // // DevExpressのTreeListはデータテーブルもしくはデータセットをそのままバインディング // すると凄く遅い。一旦、BindingSourceなどに移し変えるとぐっと早くなる。 // // trlPersonsはDataSetを直接バインディング. // trlPersons2はBindingSource経由でバインディング // if(trlPersons.Enabled){ w.Reset(); w.Start(); trlPersons.BeginUpdate(); trlPersons.DataSource = ds; trlPersons.DataMember = "Person"; trlPersons.EndUpdate(); w.Stop(); lciTree1.Text = w.Elapsed.ToString(); } BindingSource dataSource = new BindingSource(ds, "Person"); w.Reset(); w.Start(); trlPersons2.BeginUpdate(); trlPersons2.DataSource = dataSource; trlPersons2.EndUpdate(); w.Stop(); lciTree2.Text = w.Elapsed.ToString(); // // GridControlの場合は、データセットを直接バインディングしても速度的には // 大差ない。 // w.Reset(); w.Start(); grdPersons.BeginUpdate(); grdPersons.DataSource = ds; grdPersons.DataMember = "Person"; grdPersons.EndUpdate(); w.Stop(); lciGrid1.Text = w.Elapsed.ToString(); w.Reset(); w.Start(); grdPersons2.BeginUpdate(); grdPersons2.DataSource = dataSource; grdPersons2.EndUpdate(); w.Stop(); lciGrid2.Text = w.Elapsed.ToString(); formLoadingWatch.Stop(); lblFormLoading.Text = string.Format("Form Loading={0}", formLoadingWatch.Elapsed.ToString()); sttMainStatus.Caption = "Reload Complete."; } } }
[サンプルアプリ]
[DevExpressのバージョン]
- v8.1.3.0