2012-02-07 18 views
3

私たちのプロジェクトでUIを最適化すると、ListViewで本当に変わったような気がして、どこから来たのか理解できませんでした。 3815ミリ秒:BeginUpdateメソッド()+ EndUpdateの()付きWinForms ListViewとTreeView:奇妙なパフォーマンスの問題

for (int i = 0; i < 5000; i++) 
     listView1.Items.Add((Guid.NewGuid().ToString())); 

- - 2317ミリ秒:

listView1.BeginUpdate(); 
for (int i = 0; i < 5000; i++) 
    listView1.Items.Add((Guid.NewGuid().ToString())); 
listView1.EndUpdate(); 

隠すと()+:リストビューに5000個の要素(リストビュー)を追加

シンプルショー() - 163ms(NO MISTAKE、10倍以上):

listView1.Hide(); 
for (int i = 0; i < 5000; i++) 
    listView1.Items.Add((Guid.NewGuid().ToString())); 
listView1.Show(); 

スタイルも変更されました。 今は2列の代わりに4を持っています。

なぜこのように高速ですか? さらに、隠しリストビュー(Visible:false)で始まり、人口集計後にそれを表示するのが同じパフォーマンス向上をもたらさないのはなぜですか?

TreeViewとは異なります。シンプル5000個のノードの追加 - 2130ミリ秒:隠す()+ショー()で

for (int i = 0; i < 5000; i++) 
    treeView1.Nodes.Add((Guid.NewGuid().ToString())); 

から1048ミリ秒:BeginUpdateメソッド()+ EndUpdateの()付き

treeView1.Hide(); 
for (int i = 0; i < 5000; i++) 
    treeView1.Nodes.Add((Guid.NewGuid().ToString())); 
treeView1.Show(); 

から291ミリ秒:

treeView1.BeginUpdate(); 
for (int i = 0; i < 5000; i++) 
    treeView1.Nodes.Add((Guid.NewGuid().ToString())); 
treeView1.EndUpdate(); 
+1

あなたの項目をリストに追加し、 'AddRange(...) 'を呼び出すと、コントロールを動的に割り当てるようにするのではなく、手動で列を指定する必要があります。 – Seph

答えて

2

これはバグのようです。コントロールが非表示になっていると、コントロールが表示されているときに、コントロールが追加されたとき(意味があります)、アイテムのエクステント(Graphics.MeasureStringまたはその同等のもの)が計算されず、後で計算されません。おそらくバグ)。この理由から、2の代わりに4つの列が得られます.2つの列を取得すると、このサイズの計算が実行されたため、項目は切り捨てられません。 4つの列を取得すると、表示が一般に正しくありません。

なぜ最初から目に見えないようにしていないのですか?なぜなら、この場合は、Showメソッドを呼び出すか、ハンドルを強制的に作成する何かを行うまで、コントロールのハンドルは作成されない(下にあるWin32コントロールはまだ作成されていない)からです。そして、Showは初めてOnHandleCreatedを含む多くの他のコードを実行するハンドルを作成し、この時点でコードはアイテムを編成し、それらのサイズを計算します。

IsHandleCreatedプロパティがfalseであることが確認できます。コントロールが最初から目に見えない場合は、最初のShowが呼び出されます。

ハンドルを明示的に作成することもできます。

IntPtr handle = listView1.Handle; 
for (int i = 0; i < 5000; i++) 
    listView1.Items.Add((Guid.NewGuid().ToString())); 
listView1.Show(); 

ハンドルが以前に作成された場合、:高速ですが、表示が間違っている - 単に(これは、作成するハンドルを強制的に)Handleプロパティを読み取ろうとし、それは同じように動作することによりサイズ計算と共にOnHandleCreatedも呼び出されましたが、その時点ではリストは空でした。

0

要素を追加する場合、リストビュー要素は要素を描画する要素であり、リストビューを非表示にすると、すべての要素を一度に描画します。

+0

本当の質問は次のとおりです: 隠れたListView(Visible:false)から始まって、人口が同じパフォーマンスを上げないと、それを表示するのはなぜですか? なぜ表示/非表示の列数が表示されますか? – Kuba

+0

同じ答えですので、すべての要素が表示されている場合は追加しているものが単色で描画されます(新しい要素が描画されるたびに呼び出されます)。ただし、コンポーネントを隠してショー後には1つで描画します(すべての要素を追加した後、それはすべてGUI上に描画されます).. –