wpf TreeViewItem如何异步扩展节点?

时间:2017-06-21 10:36:13

标签: c# wpf

当我使用~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?”我搜索了半天......

任何建议?

0 个答案:

没有答案