-1

I want to change ListBox ItemsSource without UI freezing. For this challenge, I wrote the code that you see below;

When User Click The Button

Thread th = new Thread(DisplayFilesAsync);
th.Start(new object[] { FolderPath, fdv.FileType });

Async Method

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 });
}

Change The ItemsSource

private void DisplayFiles(IEnumerable<FileListItem> fileList)
{
     lstFiles.ItemsSource = fileList;
}

In the last method, if I change directly ItemSource of ListBox, program isn't break up but when program pass to closed curly brackets of the method, is break up and throw an Must create DependencySource on same Thread as the DependencyObject exception.

if I changed that; it's break up on closed curly brackets again, not over the ADD method and throw an same exception.

private void DisplayFiles(IEnumerable<FileListItem> fileList)
{
    foreach (FileListItem item in fileList)
    {
        lstFiles.Items.Add(item);
    }
}

But if I change the code like that, it's work perfectly and add items to my listbox.

foreach (FileListItem item in fileList)
{
    lstFiles.Items.Add("EXAMPLE");
}

I'm really don't understand to my missing. Why I can add to some string but I can't add to my FileListItem class. What am I missing? I've tried a lot of different code but it's always break on closed curly braces NOT OVER THE ASSIGMENT LINE.

I'm really need to help. Thanks for answers. Have good day, good works.

H.B.
  • 166,899
  • 29
  • 327
  • 400
  • This question might help you: http://stackoverflow.com/questions/1862590/how-to-update-gui-with-backgroundworker – EJoshuaS - Stand with Ukraine Sep 06 '16 at 17:04
  • Unfortunately, with background worker I got same error too. – Umut Çömlekçioğlu Sep 06 '16 at 17:09
  • What does your FileListItem class look like? Is it a DependcyObject? If so, you may have to create it on the UI thread. If you are having break point issues, maybe VisualStudio is not running the latest version of your code... try cleaning the project and rebuild. You might want to check that the files are actually gone after you clean and before you rebuild. – J.H. Sep 06 '16 at 17:40
  • `public class FileListItem { public FileListItem(string itemText, ImageSource itemImage, ImageSource itemToolTip) { ItemText = itemText; ItemImage = itemImage; ToolTipImage = itemToolTip; } public string ItemText { get; set; } public ImageSource ItemImage { get; set; } public ImageSource ToolTipImage { get; set; } }` This is my FileListItem... Am I derived it from Dependency Object? – Umut Çömlekçioğlu Sep 06 '16 at 19:49

1 Answers1

0

Your FileListItem class has a property of type ImageSource

public ImageSource ItemImage { get; set; }

Although you haven't show that in your question, you certainly assign a value to that property in your GetFileFromFolder method, e.g. like

fileList.ItemImage = new BitmapImage(new Uri(...));

Unless the BitmapImage is not frozen in the background thread, it can not be accessed by the UI thread, hence you get that exception.

Make sure you call the Freeze() method on the BitmapImage after it has loaded a bitmap. Note that you can't do asynchronous bitmap loading (e.g. by a remote URI) in this situation. If your bitmap is loaded from a local file, do something like this:

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;

Or, instead of BitmapImage, use the BitmapFrame.Create() method, which already returns a frozen BitmapFrame (another subclass of ImageSource).

using (var stream = new FileStream(imageFilePath, FileMode.Open, FileAccess.Read))
{
    fileList.ItemImage = BitmapFrame.Create(
        stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
Clemens
  • 123,504
  • 12
  • 155
  • 268