【问题标题】:treeview getting very slow when worked on for a couple of minutes工作几分钟后,树视图变得非常慢
【发布时间】:2013-12-19 16:23:56
【问题描述】:

正如标题中提到的,我有大量的分层结构的项目,我想在树视图控件中显示它们,除了加载时间之外,一开始性能还不错,但越长越好使用树视图(检查复选框,扩展,收缩,选择)它变得越慢,这里是示例代码(元素的数量以这样的方式选择,它们代表正常使用的实际最大元素数量,如果你用完内存只需调整创建项目的数量)

XAML 代码:

<Window x:Class="testLargeContourTree.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid Grid.Column="0">
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <TreeView  Grid.Row="0" x:Name="treeView" ItemsSource="{Binding Children}">
                <!--<TreeView.Resources>
                    <Style TargetType="TreeViewItem">
                        <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                        <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
                    </Style>
                </TreeView.Resources>-->
                <TreeView.ItemTemplate>
                    <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                        <StackPanel Orientation="Horizontal">
                            <CheckBox IsChecked="{Binding IsChecked}" />
                            <TextBlock Text="{Binding Name}" />
                        </StackPanel>                  
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>
            </TreeView>
            <Button Grid.Row="1" Content="Start" />
            <Button Grid.Row="2" Content="Stop" />
            <Button Grid.Row="3" Content="Move Up" />
            <Button Grid.Row="4" Content="Move Down" />
        </Grid>
        <TextBlock Grid.Column="1" x:Name="textOut" />
    </Grid>
</Window>

C#代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Threading;
using System.Windows.Threading;


namespace testLargeContourTree
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private MyTreeViewItem _itemCollection;

        public MainWindow()
        {
            InitializeComponent();

            _itemCollection = new MyTreeViewItem();
            MyTreeViewItem year;
            MyTreeViewItem month;
            MyTreeViewItem day;
            MyTreeViewItem job;
            MyTreeViewItem contour;
            MyTreeViewItem segment;
            Int32 numberOfJobs = 0;
            Int32 numberOfSegments = 0;
            for (Int32 i = 0; i < 2; i++)
            {
                year = new MyTreeViewItem(String.Format("{0}", 2013 + i));
                for (Int32 j = 0; j < 12; j++)
                {
                    month = new MyTreeViewItem(String.Format("{0}", (Months)j));
                    for (Int32 k = 0; k < 10; k++)
                    {
                        day = new MyTreeViewItem(String.Format("{0}", k + 1));
                        for (Int32 l = 0; l < 20; l++)
                        {
                            job = new MyTreeViewItem(String.Format("Job {0}", numberOfJobs + 1));
                            for (Int32 m = 0; m < 50; m++)
                            {
                                contour = new MyTreeViewItem(String.Format("Contour {0}", m + 1));
                                for (Int32 n = 0; n < 100; n++)
                                {
                                    segment = new MyTreeViewItem(String.Format("Segment {0}", n + 1));
                                    contour.AddChild(segment);
                                    numberOfSegments++;
                                }
                                job.AddChild(contour);
                            }
                            day.AddChild(job);
                            numberOfJobs++;
                        }
                        month.AddChild(day);
                    }
                    year.AddChild(month);
                }
                _itemCollection.AddChild(year);
            }
            treeView.DataContext = _itemCollection;
            textOut.Text = String.Format("number of segments: {0}", numberOfSegments + 1);
        }
    }

    public enum Months
    {
        Jannuary,
        February,
        March,
        April,
        May,
        June,
        July,
        August,
        September,
        October,
        November,
        December
    }


    public class MyTreeViewItem : INotifyPropertyChanged
    {
        private String _name;
        public String Name
        {
            get { return _name; }
            set { _name = value; OnPropertyChanged("Name"); }
        }
        public ObservableCollection<MyTreeViewItem> Children { get; set; }
        private Boolean _isSelected;
        public Boolean IsSelected
        {
            get { return _isSelected; }
            set { _isSelected = value; OnPropertyChanged("IsSelected"); }
        }
        private Boolean _isExpanded;
        public Boolean IsExpanded
        {
            get { return _isExpanded; }
            set { _isExpanded = value; OnPropertyChanged("IsExpanded"); }
        }
        private Boolean _isChecked;
        public Boolean IsChecked
        {
            get { return _isChecked; }
            set 
            { 
                _isChecked = value; 
                OnPropertyChanged("IsChecked");
                if (Children != null)
                {
                    ObservableCollection<MyTreeViewItem> children = Children;
                    foreach (MyTreeViewItem child in children)
                    {
                        child.IsChecked = value;
                    }
                }
            }
        }

        public MyTreeViewItem()
        {
            IsSelected = false;
            IsExpanded = false;
            IsChecked = false;
            Name = "";
            Children = new ObservableCollection<MyTreeViewItem>();
        }

        public MyTreeViewItem(String name) : this()
        {
            Name = name;
        }

        public void AddChild(MyTreeViewItem item)
        {
            Children.Add(item);
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(String propertyName)
        {
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

我知道大量内存使用和大量元素,但是,我希望在使用过程中性能大致相同

我在某处读到,如果 inotifypropertychanged 未正确使用,可能存在内存泄漏,我尝试遵循提供的建议,但它并没有改变这种行为,除了留有足够内存的接缝

所以我想请教任何关于如何稳定性能的建议

我的猜测是当父元素展开时元素会按需加载,但如果它们收缩则不会卸载,但是我对 wpf 树视图的背景机制没有足够的了解,所以即使是一个好的深入了解后者将非常有帮助

【问题讨论】:

    标签: c# wpf performance treeview


    【解决方案1】:

    因为要创建的节点太多,请尝试在树上设置虚拟化。

    <TreeView VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling">
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-08
      • 1970-01-01
      相关资源
      最近更新 更多