无法从 BackgroundWorker 更新图像绑定

Can't update Image binding from BackgroundWorker

我得到:

"An unhandled exception of type 'System.Windows.Markup.XamlParseException' occurred in PresentationFramework.dll

Additional information: Must create DependencySource on same Thread as the DependencyObject."

XAML:

  <ListBox x:Name="AutoListBox" ItemsSource="{Binding AutoList}" Visibility="{Binding AutoListVisibility}">
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                   <EventSetter Event="MouseDoubleClick" Handler="EventSetter_OnHandler"></EventSetter>
                </Style>
            </ListBox.ItemContainerStyle>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition Width="5"/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
                        <Image Source="{Binding ImgSource}"></Image>
                        <Label Content="{Binding Name}"></Label>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

视图模型:

    private Visibility isBusyVisibility;

    public Visibility IsBusyVisibility
    {
        get { return isBusyVisibility; }
        set
        {
            isBusyVisibility = value;
            RaisePropertyChanged("IsBusyVisibility");
        }
    }

    private ObservableCollection<GenericPictureName> autoList;

    public ObservableCollection<GenericPictureName> AutoList
    {
        get { return autoList; }
        set
        {
            autoList = value;
            RaisePropertyChanged("AutoList");
        }
    }
public AutoAlbumTrackAssociationViewModel()
    {
        _bwArtist = new BackgroundWorker();
        _bwArtist.DoWork += bwArtist_DoWork;
    }

private void bwArtist_DoWork(object sender, DoWorkEventArgs e)
    {
        AutoList = new ObservableCollection<GenericPictureName>(LastFMLookup.ArtistQuery(e.Argument.ToString()));

        RaisePropertyChanged("AutoList");
        RaisePropertyChanged("IsBusyVisibility");
    }

型号:

public class GenericPictureName
{
    private string name;

    public string Name
    {
        get { return name; }
        set
        {
            name = value;
        }
    }

    private ImageSource imgSource;

    public ImageSource ImgSource
    {
        get { return imgSource; }
        set
        {
            imgSource = value;
        }
    }


    public GenericPictureName()
    {

    }

    public GenericPictureName(string name, string image)
    {
        Name = name;
        var bitmapImage = new BitmapImage();
        bitmapImage.BeginInit();
        bitmapImage.UriSource = new Uri(image); ;
        bitmapImage.EndInit();
        ImgSource = bitmapImage;
    }

}

如果我从 XAML 文件中删除图像的绑定,我会在 UI 中取回一个可以正常显示名称的列表。我还做了一个没有使用 backgroundworker 的测试方法来验证它是否正常工作。我也尝试调用主线程,但仍然出现相同的错误。我不确定接下来要尝试什么。

如果image参数是指本地文件,通过设置BitmapCacheOption.OnLoad指定立即加载BitmapImage应该就可以了,然后冻结它。

public GenericPictureName(string name, string image)
{
    Name = name;
    var bitmapImage = new BitmapImage();
    bitmapImage.BeginInit();
    bitmapImage.UriSource = new Uri(image);
    bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
    bitmapImage.EndInit();
    bitmapImage.Freeze();
    ImgSource = bitmapImage;
}

如果是远程资源,您可以先下载图像缓冲区并将其放入 MemoryStream,最后从中加载图像:

public GenericPictureName(string name, string image)
{
    Name = name;
    var bitmapImage = new BitmapImage();
    var imageBuffer = new WebClient().DownloadData(image);
    using (var ms = new MemoryStream(imageBuffer))
    {
        bitmapImage.BeginInit();
        bitmapImage.StreamSource = ms;
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
        bitmapImage.EndInit();
    }
    bitmapImage.Freeze();
    ImgSource = bitmapImage;
}

尝试在您的 collection

上设置 EnableCollectionSynchronization
BindingOperations.EnableCollectionSynchronization(AutoList, _itemsLock);

然后在您的辅助方法中对其进行 clear() 和 Add(),而不是重新创建它