通常の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