用不同的线程改变列表框ItemsSource
本文关键字:列表 ItemsSource 改变 线程 | 更新日期: 2023-09-27 18:05:49
我想改变ListBox ItemsSource没有UI冻结。对于这个挑战,我编写了如下代码;
当用户单击按钮
Thread th = new Thread(DisplayFilesAsync);
th.Start(new object[] { FolderPath, fdv.FileType });
异步方法
private void DisplayFilesAsync(object param)
{
object[] args = param as object[];
string searchText = Convert.ToString(args[0]);
FileType type = (FileType)args[1];
IEnumerable<FileListItem> list = uDirectoryHelper.GetFileFromFolder(searchText, type);
Dispatcher.BeginInvoke(new Action<IEnumerable<FileListItem>>(DisplayFiles), DispatcherPriority.Background, new object[] { list });
}
改变ItemsSource
private void DisplayFiles(IEnumerable<FileListItem> fileList)
{
lstFiles.ItemsSource = fileList;
}
在最后一个方法中,如果我直接改变ListBox的ItemSource,程序不会中断,但是当程序传递到方法的右花括号时,它会中断并抛出必须在与DependencyObject异常相同的线程上创建DependencySource。
如果我改变了;它再次在右花括号上断开,而不是在ADD方法上并抛出相同的异常。
private void DisplayFiles(IEnumerable<FileListItem> fileList)
{
foreach (FileListItem item in fileList)
{
lstFiles.Items.Add(item);
}
}
但是如果我像那样修改代码,它就可以完美地工作,并将项目添加到我的列表框中。
foreach (FileListItem item in fileList)
{
lstFiles.Items.Add("EXAMPLE");
}
我真的不明白我的思念。为什么我可以添加到一些字符串,但我不能添加到我的FileListItem类。我错过了什么?我试过很多不同的代码,但它总是在不超过赋值线的闭花括号上中断。
我真的需要帮忙。谢谢你的回答。祝你有美好的一天,美好的工作。
你的FileListItem类有一个ImageSource类型的属性
public ImageSource ItemImage { get; set; }
虽然你没有在你的问题中显示,你肯定会在你的GetFileFromFolder
方法中为该属性分配一个值,例如
fileList.ItemImage = new BitmapImage(new Uri(...));
除非BitmapImage
没有被冻结在后台线程中,否则UI线程无法访问它,因此你会得到那个异常。
确保在BitmapImage加载位图后调用Freeze()
方法。请注意,在这种情况下,您不能进行异步位图加载(例如通过远程URI)。如果您的位图是从本地文件加载的,请执行如下操作:
var bitmap = new BitmapImage();
using (var stream = new FileStream(imageFilePath, FileMode.Open, FileAccess.Read))
{
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = stream;
bitmap.EndInit();
bitmap.Freeze();
}
fileList.ItemImage = bitmap;
或者,代替BitmapImage,使用BitmapFrame.Create()
方法,它已经返回一个冻结的BitmapFrame
(ImageSource
的另一个子类)。
using (var stream = new FileStream(imageFilePath, FileMode.Open, FileAccess.Read))
{
fileList.ItemImage = BitmapFrame.Create(
stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}