无法从 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(),而不是重新创建它
我得到:
"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
上设置 EnableCollectionSynchronizationBindingOperations.EnableCollectionSynchronization(AutoList, _itemsLock);
然后在您的辅助方法中对其进行 clear() 和 Add(),而不是重新创建它