2011-01-13 3 views
2

Ich habe festgestellt, dass das Kontextmenü mehr als 10 Sekunden dauert, um 10.000 Objekte anzuzeigen. Ich möchte es schneller machen (z. B. weniger als 1 Sekunde)WPF Contextmenu ist langsam mit vielen Elementen - wie kann ich es beschleunigen?

Hier ist mein Testcode, der den Kontext zeigt Menü Langsamkeit direkt:

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% 
     } 

nach Performance Profiler ich verwendet habe, die cm.IsOpen die meiste Zeit nimmt - aber die mi.Header Einstellung ist ebenfalls von Bedeutung.

+6

Warum sind Sie ein unbrauchbares Kontextmenü zu machen? – SLaks

+2

Genau meine Gedanken ... Menüs funktionieren gut mit ungefähr bis zu 9 Elementen. 10k Gegenstände darin zu stopfen ist nicht nur Unsinn, es ist verrückt. – Joey

+2

Woah, 10000 Elemente in einem Kontextmenü, ich würde das Kontextmenü nicht mögen. – Gabe

Antwort

7

Es wird eine schlechte Benutzererfahrung mit 1k Elemente auf einer einzigen Ebene sein, aber wie Kontextmenüs mit vielen \ teuren Elemente reaktionsfähiger machen, ist eine faire Frage.

Das allgemeine Muster, das ich verwende, besteht darin, zunächst mein Menü mit Dummy-Untermenüs zu erstellen. Die Dummy-Untermenüs haben einen einzelnen Platzhalter-Menüpunkt und ich höre das Untermenü-Öffnungsereignis. Im Event-Handler entferne ich den Platzhalter-Menüeintrag und füge die realen Artikel hinzu.

Mit diesem Muster können Untermenüs auf Anfrage und nur dann erstellt werden, wenn das Untermenü tatsächlich geöffnet ist. Mit anderen Worten, Ihr Menü wird dynamischer, dh Sie müssen nicht alles im Voraus erstellen oder Hunderte von Untermenüs erstellen, die nicht geöffnet werden.

Dieses Muster würde die Anzahl der ursprünglichen Menüelemente von 10.000 auf 1 KB für das obige Beispiel reduzieren. Das sollte dich auf ~ 1 Sekunde bringen.

Wieder 10k Menüpunkte mit 1k im root ist ziemlich unbrauchbar in Bezug auf UX. Ich hoffe, das ist nur ein Gedankenexperiment! :)

Beispiel

 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

Ja, das macht es viel schneller. Der Grund für so viele Dinge liegt außerhalb meiner Kontrolle - und ich stimme @Joey zu, dass es gut ist, zu viele Ebenen zu vermeiden. Hoffentlich sobald ich es schneller mache, werden sich die Benutzer stattdessen über die Praktikabilität beschweren und sich für Veränderungen entscheiden. – Lance

+0

@Lance Klingt nach einer interessanten Situation. Glücklich, um Hilfe zu sein. :) –

+0

@chibacity: danke für ein schönes, übersichtliches Arbeitsbeispiel für die dynamische Generierung von Untermenüs! –