Контекстное меню WPF медленное со многими элементами - как я могу ускорить его? - PullRequest
2 голосов
/ 14 января 2011

Я обнаружил, что для отображения контекстного меню требуется более 10 секунд, когда у меня есть 10 000 элементов, я хотел бы сделать это быстрее (например, менее 1 секунды)

Вот мой тестовый код, который напрямую показывает медлительность контекстного меню:

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 также важна.

1 Ответ

7 голосов
/ 14 января 2011

Это будет плохой пользовательский опыт с 1 тыс. Элементов на одном уровне, но вопрос о том, как сделать контекстные меню с большим количеством дорогих элементов более отзывчивым, - справедливый вопрос.

Общий шаблон, который я использую, - это изначально создать мое меню с фиктивными подменю. Подменю-пустышка содержат один элемент меню заполнителя, и я перехватываю событие открытия подменю. В обработчике событий я удаляю элемент меню заполнителя и добавляю реальные элементы.

Этот шаблон позволяет создавать подменю по требованию и только в том случае, если подменю действительно открыто. Другими словами, это делает ваше меню динамичным, то есть вам не нужно создавать все заранее и создавать сотни подменю, которые не будут открыты.

Этот шаблон уменьшит исходное количество пунктов меню с 10 000 пунктов до 1 000 для примера выше. Это должно привести вас к ~ 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...