当我使用~3000项扩展TreeViewItem时,应用程序将被卡住约5秒钟。在寻找解决方案后,我意识到编写自定义虚拟化面板是唯一的方法,但对我来说很难。
这是我正在使用的xaml(简化):
<controls:FileMapPresenter ItemsSource="{Binding RootSource, Mode=OneWay}"
ItemTemplateSelector="{StaticResource templateSelector}">
<controls:FileMapPresenter.Resources>
<DataTemplate x:Key="folder_template">
<controls:FolderDataPersenter ItemsSource="{Binding Source, Mode=OneWay}"
ItemTemplateSelector="{StaticResource templateSelector}">
<controls:FolderDataPersenter.Header>
<TextBlock Text="{Binding Name, Mode=OneWay}" />
</controls:FolderDataPersenter.Header>
</controls:FolderDataPersenter>
</DataTemplate>
<DataTemplate x:Key="file_template">
<TextBlock Text="{Binding Name, Mode=OneWay}" />
</DataTemplate>
</controls:FileMapPresenter.Resources>
</controls:FileMapPresenter>
控件:FileMapPresenter 派生自 ItemsControl ,控件:FolderDataPersenter 派生自 TreeViewItem 。
FolderDataModel(简化):
public class FolderData : ViewModelBase
{
public FolderData(string name)
{
this.name = name;
}
private List<FileData> files = new List<FileData>();
public List<FileData> Files
{
get { return this.files; }
}
private List<FolderData> subFolders = new List<FolderData>();
public List<FolderData> SubFolders
{
get { return this.subFolders; }
}
private string name;
public string Name
{
get { return this.name; }
}
private AutoInvokeObservableCollection<object> source =
new AutoInvokeObservableCollection<object>();
/// <summary>
/// ObservableCollection which contains all the files and subFolders
/// </summary>
public AutoInvokeObservableCollection<object> Source
{
get { return this.source; }
}
}
FileDataModel(简化):
public class FileData
{
public FileData(string name)
{
this.name = name;
}
private string name;
public string Name
{
get { return this.name; }
}
}
控件中的:FolderDataPersenter,我尝试取消扩展调用并将其置于异步中,然后添加一个展开进度报告器来通知UI:
public class FolderDataPersenter : TreeViewItem
{
public FolderDataPersenter()
{
VirtualizingStackPanel.SetIsVirtualizing(this, true);
VirtualizingStackPanel.SetVirtualizationMode(this, VirtualizationMode.Recycling);
this.Dispatcher.BeginInvoke(
(Action)this.setExpandingEventListener,
System.Windows.Threading.DispatcherPriority.Loaded);
}
private void setExpandingEventListener()
{
if (this.Template != null)
{
var expander = this.Template.FindName("Expander", this) as ToggleButton;
if (expander != null)
{
expander.PreviewMouseLeftButtonDown += this.onExpanderPreviewMouseLeftButtonDown;
}
}
}
private void onExpanderPreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
e.Handled = true;
this.Dispatcher.BeginInvoke((Action)delegate
{
this.IsExpanded = !this.IsExpanded; // no work here
}, System.Windows.Threading.DispatcherPriority.Background);
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
Business.TreeViewExpandingCounter.StepForward();
}
protected override void OnExpanded(RoutedEventArgs e)
{
var folder = this.DataContext as Models.FolderData;
if (folder != null)
{
if (folder.SubFolders.Count > 100)
{
Business.TreeViewExpandingCounter.Finish += this.onExpandingCounterDone;
Business.TreeViewExpandingCounter.Set(folder.SubFolders.Count);
}
}
base.OnExpanded(e);
}
private void onExpandingCounterDone()
{
Business.TreeViewExpandingCounter.Finish -= this.onExpandingCounterDone;
}
}
扩展进度记者运行良好但异步扩展失败,应用程序在扩展节点时仍然停滞不前。
所以我似乎回到了第一个问题“如何更快地扩展TreeViewItem?”我搜索了半天......
任何建议?