WPF上下文菜单很慢,有很多项目 - 我怎样才能加快速度?

Lan*_*nce 3 c# wpf contextmenu

我发现当我有10,000个项目时,上下文菜单需要超过10秒才能显示,我想让它更快(例如不到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%
        }
Run Code Online (Sandbox Code Playgroud)

根据我使用的性能分析器,cm.IsOpen占用了大部分时间 - 但设置mi.Header也很重要.

Tim*_*oyd 7

这将是一个糟糕的用户体验,在一个级别上拥有1k项目,但是如何制作具有更多\昂贵项目的上下文菜单更具响应性,这是一个公平的问题.

我使用的一般模式是最初使用虚拟子菜单创建我的菜单.虚拟子菜单有一个占位符菜单项,我挂钩子菜单打开事件.在事件处理程序中,我删除了占位符菜单项并添加了实际项目.

此模式允许按需创建子菜单,并且只有在实际打开子菜单时才能创建子菜单.换句话说,它使您的菜单动态化意味着您不必预先创建所有内容,也不必创建数百个不会打开的子菜单.

对于上面的示例,此模式会将初始菜单项数从10k项减少到1k.这应该会让你减少到1秒钟.

在根目录中,根目录中有1k的10k菜单项几乎无法使用.我希望这只是一个思想实验!:)

        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;
Run Code Online (Sandbox Code Playgroud)