Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将大IEnumerable设置为ListBox.ItemSource的最佳方法_C#_Wpf_Listbox_Windows Api Code Pack - Fatal编程技术网

C# 将大IEnumerable设置为ListBox.ItemSource的最佳方法

C# 将大IEnumerable设置为ListBox.ItemSource的最佳方法,c#,wpf,listbox,windows-api-code-pack,C#,Wpf,Listbox,Windows Api Code Pack,我正在尝试使用Microsoft.Windows.APICodePack.Shell.ShellContainer作为ListBox的ItemsSource,通过ListBox.ItemTemplate显示每个子对象(ShellObject)的缩略图和名称。 当ShellContainer引用一个非常大的文件夹(比如超过1000个文件)时,问题就出现了:如果我简单地声明 ShellContainer source=ShellObject.FromParsingName(@"C:\MyFo

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

    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);
    }
}
class-AsyncSourceFiller
{
私有可观测采集源;
私有容器路径;
私人控股母公司;
私人物品;
公共AsyncSourceFiller(ObservableCollection源、ShellContainer路径、控件父级)
{
this.source=源;
this.path=path;
this.parent=parent;
}
填空
{
foreach(路径中的ShellObject对象)
{
项目=obj;
parent.Dispatcher.Invoke(新操作(添加));
睡眠(4);
}
}
私有void Add()
{
来源.添加(项目);
}
}
然后通过

    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();
observetecollection source=新的observetecollection();
listBox1.ItemsSource=源;
ShellContainer路径=ShellObject.FromParsingName(@“C:\MyFolder”):
AsyncSourceFiller=新的AsyncSourceFiller(源、路径、此);
螺纹th=新螺纹(填料填充);
th.IsBackground=true;
th.Start();
这比前一种方法需要更多的时间,但不会冻结UI并立即开始显示某些内容。
有没有更好的方法来获得类似的行为,可能会缩短总操作时间?

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

耗时的操作是枚举
ShellContainer
并创建数千个
ShellObject
<代码>列表框不是问题所在

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

您在这里没有很多选项:

  • 自己创建一个
    列表
    ,并将其设置为
    列表框
    的源。它不会更快,但至少可以向用户显示“正在加载,请稍候”消息

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

  • 找到一种方法,将您的
    shell容器
    包装在实现
    IList
    的类中。为此,您需要能够在
    ShellContainer
    类(我不知道“Windows API代码包”)中的给定索引处获取一个项。如果您将其用作
    列表框的源,并且启用了虚拟化,则只会加载显示的
    外壳对象
    s,并且它将快速平滑


谢谢。虚拟化解决了我的问题,但据我所知,它只能通过VirtualzingStackPanel提供,在我的列表框中,我需要一个包装。我正在调查自己实现一个的可行性,但这似乎远远超出了我的本领,更不用说第三方的选择了:或者它们非常昂贵,或者它们看起来像是有缺陷的和近似的……谢谢。请告诉我更多关于这个IList接口的信息,以及它对我的情况有什么帮助。。。