简体   繁体   English

WPF上下文菜单在很多项目上都很慢-如何加快速度?

[英]WPF contextmenu is slow with many items - how can I speed it up?

I have found the context menu takes over 10 seconds to display when I have 10,000 items in it, I'd like to make this faster (eg less than 1 second) 我发现上下文菜单在有10,000个项目时需要花费10秒钟以上的时间显示,我想使其更快(例如,少于1秒)

Here is my test code that shows the context menu slowness directly: 这是我的测试代码,直接显示了上下文菜单的慢度:

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

According to performance profilers I've used, the cm.IsOpen is taking most of the time - but setting the mi.Header is also significant. 根据我使用过的性能分析器,cm.IsOpen占用了大多数时间-但是设置mi.Header也很重要。

It's going to be a poor user experience having 1k items at a single level, but how to make context menus with lots\\expensive items more responsive, is a fair question. 在单个级别上具有1k项将是糟糕的用户体验,但是如何使包含大量\\昂贵项的上下文菜单更敏感,这是一个公平的问题。

The general pattern I use is to initially create my menu with dummy sub-menus. 我使用的一般模式是首先使用虚拟子菜单创建菜单。 The dummy sub-menus have a single place-holder menu item and I hook the sub-menu opening event. 虚拟子菜单有一个占位符菜单项,我钩住了子菜单打开事件。 In the event handler I remove the place-holder menu item and add the real items in. 在事件处理程序中,我删除了占位符菜单项并添加了真实项。

This pattern allows sub-menus to be created on demand and only if the sub-menu is actually opened. 此模式允许按需创建子菜单,并且仅在实际打开子菜单时才可以创建。 In other words it makes your menu dynamic meaning you do not have to create everything up-front, nor create hundreds of sub-menus which will not be opened. 换句话说,它使菜单变得动态,这意味着您不必先创建所有内容,也不必创建数百个不会打开的子菜单。

This pattern would reduce your initial menu item count from 10k items to 1k for the example above. 对于上述示例,此模式会将您的初始菜单项数从10k减少到1k。 This should get you down to ~1 second. 这应该使您下降到〜1秒。

Again 10k menu items with 1k in the root is pretty much unusable in terms of UX. 同样,在UX方面,以1k为根的10k菜单项几乎是不可用的。 I hope this is just a thought experiment! 我希望这只是一个思想实验! :) :)

Example

        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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM