I have a problem, with my WPF application. I'm trying to databind an image field, in my gridview, with the image property from my viewmodel.

<DataGridTemplateColumn Header="Image" IsReadOnly="True">
    <DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <Image Source="{Binding Path=Image, IsAsync=True}" />
    </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

This is no problem, if I don't use IsAsync. However, I would like to do it async, as it's a lot of images to load, and it needs to load them from a webservice.

The code for the Image property is this, which just calls a handler dll, that calls a webservice.

    public BitmapSource Image
    {
        get { return image ?? (image = ImageHandler.GetDefaultImages(new[] {ItemNumber},160,160)[0].BitmapSource()); }
    }

But, as soon as I add the IsAsync=true, I get the following exception, once the form has loaded:

The calling thread cannot access this object because a different thread owns it.

I am quite new to WPF, and I kind of assumed, that it handled the threading itself, when async was set to true. Do I need to somehow invoke, in the databinding? If so, how on earth do I do this?

有帮助吗?

解决方案

IsAsync means that the bound property will be accessed from another thread, so make sure that whatever you're creating can then be used in a cross-thread manner. The final step of the binding will always occur on the main thread.

Almost all classes in WPF inherit from DispatcherObject, which basically 'links' an object to the current thread when it's created. The BitmapSource in your code is created on another thread and then cannot be used on the main UI thread.

However, BitmapSource inherits from Freezable: simply call the Freeze method on your BitmapSource before returning, to make it immutable and usable from any thread.

其他提示

How about if you access the image on separate thread and don't use IsAsync. Something like

public BitmapSource Image
    {
        get 
        { 
            return image ?? (Task.Factory.StartNew(() => image = ImageHandler.GetDefaultImages(new[] { ItemNumber }, 160, 160)[0].BitmapSource());) 
        }
    }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top