【问题标题】:Best way to set BIG IEnumerable as ListBox.ItemSource将 BIG IEnumerable 设置为 ListBox.ItemSsource 的最佳方法
【发布时间】:2012-05-07 07:09:20
【问题描述】:

我正在尝试使用 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();

这比以前的方式花费更多时间,但不会冻结 UI 并立即开始显示一些内容。 有没有更好的方法来获得类似的行为,可能会缩短总操作时间?

【问题讨论】:

    标签: c# wpf listbox windows-api-code-pack


    【解决方案1】:

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

    【讨论】:

    • 谢谢。虚拟化解决了我的问题,但据我所知,它只能通过 VirtualizingStackPanel 获得,并且在我的 ListBox 中我需要一个 WrapPanel。我正在调查自己实施一个的可行性,但这似乎远远超出了我的卑微技能,更不用说第三方选项了:或者它们非常昂贵,或者它们看起来有问题和近似......
    【解决方案2】:

    耗时的操作是枚举你的ShellContainer并创建数千个ShellObjectListBox 不是问题。

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

    这里没有太多选择:

    • 为自己创建一个List&lt;ShellObject&gt; 并将其设置为我们ListBox 的来源。它不是更快,但至少您可以向您的用户显示“正在加载,请稍候”消息。

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

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

    【讨论】:

    • 谢谢。请告诉我有关此 IList 接口的更多信息,以及它对我的情况有何帮助...
    猜你喜欢
    • 2010-10-04
    • 2011-10-19
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多