TabControl变得非常迟钝

时间:2014-03-22 15:47:04

标签: wpf tabcontrol lag

我们正在使用Tabcontrol来显示内容相当昂贵的项目,而我们遇到的问题是,当您迭代选项卡(逐个选择它们)时,响应性如下:应用程序变得越来越慢。

根据我的理解,这种行为是出乎意料的,因为所选标签发生了更改,之前选择的标签内容会先卸载,这样您一次只能为一个标签内容付费。

我设法使用下面的代码模拟行为。重现:

  • 运行应用程序
  • 启动选定的标签contextmenu(标签标题contextmenu),它会响应
  • 从左到右,浏览每个标签,逐个选择
  • 当你到达tab~10时,它的上下文菜单的响应性现在非常滞后,当你点击一个复选框时,它的动画需要几秒钟才能完成

    <Window x:Class="WpfApplication4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        WindowStartupLocation="CenterScreen">
    <Window.Resources>
        <Style TargetType="{x:Type TabItem}"
               BasedOn="{StaticResource {x:Type TabItem}}">
            <Setter Property="ContextMenu">
                <Setter.Value>
                    <ContextMenu>
                        <CheckBox Content="CheckBox" />
                        <CheckBox Content="CheckBox" />
                        <CheckBox Content="CheckBox" />
                        <CheckBox Content="CheckBox" />
                        <CheckBox Content="CheckBox" />
                    </ContextMenu>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <TabControl Name="tabControl" />
    

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
    
            for (int i = 0; i < 25; i++)
            {
                CreateTab();
            }
        }
    
        void CreateTab()
        {
            var itemsControl = new ItemsControl();
            for (int i = 0; i < 1000; ++i)
            {
                itemsControl.Items.Add(new TextBox());
            }
    
            tabControl.Items.Add(new TabItem()
            {
                Header = string.Format("Tab{0}", tabControl.Items.Count),
                Content = itemsControl
            });
        }
    }
    

1 个答案:

答案 0 :(得分:1)

我不确定您的复杂情况是什么,但对于发布的示例,问题不在tabControl中,而是在ItemsControl

默认情况下

ItemsControl不支持UI虚拟化,您必须使其虚拟化UI,即每当TabItem加载时,将创建所有用于托管项目的UI容器,即将创建1000个项目。

您可以通过将ItemsControl替换为ListBox来验证这一点,并且您可以看到性能大幅提升,因为ListBox默认支持UI虚拟化,并且只会创建可见项目的容器(可能是100时间)。


替换

var itemsControl = new ItemsControl();

var itemsControl = new ListBox();

你将看到性能上的差异。

如果您想要使用ItemsControl获得一些性能,则必须使其虚拟化UI。请参阅答案here以使其虚拟化UI。


<强>更新

评论:

  

问题是应用程序变得越来越慢   选择不同的标签。这是出乎意料的。由于每个项目   在加载新项目之前卸载并且由于每个项目都有   相同的内容,我希望响应能力保持不变。

是的,你是对的,Unloaded事件被调用最后选择的标签项的内容,但它只从Visual Tree断开ItemsControl。然而,它的容器保持完整并留在记忆中。因此,每个开关都会在内存中创建新的容器。我认为这是你的申请迟缓的公平理由。

您可以通过挂钩StatusChanged事件进行验证:

itemsControl.ItemContainerGenerator.StatusChanged += (s, e) => { };

您将看到每次切换到新tabItem时都会调用它两次,但在切换到已访问过的tabItem时不会调用它。

相关问题