如标题中所提到的,我在层次结构中有大量项目,我想在树视图控件中显示它们,除了加载时间之外,在开始时性能还不错,但是工作时间越长使用树视图(检查复选框,扩展,收缩,选择)得到的速度越慢,这里是示例代码(以这种方式选择元素的数量,它们表示正常使用的实际最大元素数,如果你的内存耗尽只是调整创建项目的数量)
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树视图的背景机制没有足够的了解,所以即使是好的洞察后者将非常有帮助
答案 0 :(得分:0)
由于您创建了如此多的节点,请尝试在树上设置虚拟化。
<TreeView VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling">