2011-01-13 28 views
2

コンテキストメニューに10,000個のアイテムがあるときに表示するのに10秒以上かかることがわかりました。これをもっと速くしたいです(例えば1秒未満)WPFコンテキストメニューは多くの項目で遅いです - どうすれば速くできますか?

ここに私のテストコードがありますメニュー遅さは、直接:

private void button1_Click(object sender, RoutedEventArgs e) 
     {    
      ContextMenu cm = new ContextMenu(); 

      for (int i = 0; i < 1000; i++) 
      { 
       MenuItem mi = new MenuItem(); 
       mi.Header = "test";     // this is HOT - 3% 
       mi.Tag = this;      // cold 
       for (int j = 0; j < 10; j++) 
       { 
        MenuItem mi2 = new MenuItem(); // this is HOT - 1% 
        mi2.Header = "test";   // this is HOT - 12% 
        mi2.Tag = this;     // cold 
        mi.Items.Add(mi2);    // this is HOT - 6% 
       } 
       cm.Items.Add(mi);     // this is HOT - 3% 
      } 
      cm.IsOpen = true;      // this is HOT - 72% 
     } 

私が使用したパフォーマンスプロファイラによると、cm.IsOpenは、ほとんどの時間を取っている - しかし、mi.Headerも重要である設定します。

+6

なぜあなたは使用できないコンテキストメニューを作っていますか? – SLaks

+2

まさに私の思考...メニューは約9項目までうまく機能します。 10kのアイテムを詰め込むのはナンセンスだけでなく、気違いです。 – Joey

+2

Woah、コンテキストメニューの10000項目、私は上記のコンテキストメニューを嫌いです。 – Gabe

答えて

7

1つのレベルで1k個のアイテムを持つユーザーエクスペリエンスは悪くなりますが、高価なアイテムを多数用意したコンテキストメニューをより反応性の高いものにするには、問題はありません。

私が使用する一般的なパターンは、最初にダミーのサブメニューでメニューを作成することです。ダミーサブメニューにはプレースホルダーメニュー項目が1つあり、サブメニューのオープニングイベントをフックします。イベントハンドラでは、プレースホルダメニュー項目を削除して実際の項目を追加します。

このパターンでは、サブメニューが実際に開かれた場合にのみオンデマンドでサブメニューを作成できます。言い換えれば、それはあなたのメニューを動的にして、すべてを先に作成する必要はなく、何もない何百ものサブメニューを作成する必要はありません。

このパターンは、上記の例では、最初のメニュー項目数を10k項目から1kに減らします。これは、〜1秒にあなたを得る必要があります。

もう一度10kのメニュー項目は、ルートに1kを置くとUXの点ではほとんど使用できません。これはちょうど思考実験であることを願っています! :)

 ContextMenu cm = new ContextMenu(); 

     for (int i = 0; i < 1000; i++) 
     { 
      MenuItem mi = new MenuItem(); 
      mi.Header = "test"; 
      mi.Tag = this; 

      object dummySub = new object(); 
      mi.Items.Add(dummySub); 
      cm.Items.Add(mi); 

      mi.SubmenuOpened += delegate 
      { 
       mi.Items.Clear(); 

       for (int j = 0; j < 10; j++) 
       { 
        MenuItem mi2 = new MenuItem(); 
        mi2.Header = "test"; 
        mi2.Tag = this; 
        mi.Items.Add(mi2); 
       } 
      }; 
     } 

     cm.IsOpen = true; 
+0

はい、これははるかに高速になります。非常に多くのアイテムの理由は私のコントロール外です - そして、私は@ジョイに同意すると、あまりにも多くのレベルを避けることが良いです。うまくいけば、私はそれを速くすると、ユーザーは代わりにそれの実用性について不満を持ち始め、変更を選ぶでしょう。 – Lance

+0

@Lance興味深い状況のように聞こえます。助けになるのが楽しいです。 :) –

+0

@chibacity:ダイナミックサブメニュー生成の素晴らしく実用的な例をありがとう! –

関連する問題