2

我正在尝试使用 Microsoft.Windows.APICodePack.Shell.ShellContainer 作为 ListBox 的 ItemsSource,通过 ListBox.ItemTemplate 显示每个孩子的(ShellObject)缩略图和名称。当 ShellContainer 引用一个非常大的文件夹(比如一千多个文件)时,就会出现问题:如果我只是声明

    ShellContainer source=ShellObject.FromParsingName(@"C:\MyFolder") as ShellContainer:
    listBox1.ItemsSource=source.GetEnumerator();

它会冻结 UI 两三分钟,然后立即显示 ShellContainer 的所有内容。我发现的最好的解决方法是创建一个像这样的异步填充类

class AsyncSourceFiller
{
    private ObservableCollection<ShellObject> source;
    private ShellContainer path;
    private Control parent;
    private ShellObject item;

    public AsyncSourceFiller(ObservableCollection<ShellObject> source, ShellContainer path, Control parent)
    {
        this.source = source;
        this.path = path;
        this.parent = parent;
    }

    public void Fill()
    {
        foreach (ShellObject obj in path)
        {
            item = obj;
            parent.Dispatcher.Invoke(new Action(Add));
            Thread.Sleep(4);
        }
    }

    private void Add()
    {
        source.Add(item);
    }
}

然后通过调用它

    ObservableCollection<ShellObject> source = new ObservableCollection<ShellObject>();
    listBox1.ItemsSource = source;
    ShellContainer path = ShellObject.FromParsingName(@"C:\MyFolder"):
    AsyncSourceFiller filler = new AsyncSourceFiller(source, path, this);
    Thread th = new Thread(filler.Fill);
    th.IsBackground = true;
    th.Start();

This takes more time than the previous way, but doesn't freeze the UI and begins to show some content immediately. Is there any better way to obtain a similar behavior, possibly shortening total operation time?

4

2 回答 2

1

在后台线程中加载所有数据,并在完成后更新列表框的项目源。并且不要忘记在列表框中将 Virtualization 设置为 true。

于 2012-05-07T07:41:48.187 回答
0

耗时的操作是枚举您ShellContainer并创建数千个ShellObject. ListBox不是问题。

当您将 anIEnumerable作为源设置为 anItemControl时,我认为它会在第一次显示时从枚举器中创建和内部列表,这就是为什么它会在显示任何内容之前冻结两分钟。

您在这里没有太多选择:

  • 创建自己 aList<ShellObject>并将其设置为我们的ListBox. 它不是更快,但至少您可以向您的用户显示“正在加载,请稍候”消息。

  • 在另一个线程中加载列表(就像你一样)并在加载时显示项目。随着时间的推移,列表“增长”,这有点奇怪。

  • 找到一种方法将您包装ShellContainer在一个实现IList. 为此,您需要能够在ShellContainer类中的给定索引处获取项目(我不知道“Windows API 代码包”)。如果你使用它作为你的来源ListBox并且启用了虚拟化,那么只会ShellObject加载显示的s,并且它会快速流畅。

于 2012-05-07T08:02:57.800 回答