I've struggling for a while with strange DataBinding problem that only appears to be happening in WinRT. My Phone Project uses the same code and works without problems.
The first version of the code below doesn't work on WinRT while the second version does. The confusing thing is that I was under the assumption that the call to the "Icon" getter will always come from the UI thread and thus the synchronization context used for the async "DownloadIcon" method will be the right one. But apparently it is not.
What's even more confusing is that I've verified that I'm on the same thread (Thread 3) when the getter is accessed and when the setter raises the PropertyChanged event - regardless of the code version. But only the second version has the disired effect of the Icon propery getting re-queried after the download is complete.
Binding:
<DataTemplate x:Key="AppBarAlbumItemTemplateGrid">
<Grid HorizontalAlignment="Left" Width="80" Height="80">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
</Grid.RowDefinitions>
<Border Grid.RowSpan="2" Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image Source="{Binding Icon}" Stretch="UniformToFill" />
</Border>
<Grid Grid.Row="1" VerticalAlignment="Bottom" Background="{StaticResource GIFPlayerOverlayBrush}">
<TextBlock Text="{Binding Title}" VerticalAlignment="Center" FontSize="10" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Margin="5,0"/>
</Grid>
</Grid>
</DataTemplate>
This does not work properly:
public class Album : AlbumBase
{
WeakReference<ImageSource> icon;
public ImageSource Icon
{
get
{
ImageSource result;
if (icon != null && icon.TryGetTarget(out result))
return result;
DownloadIcon();
return null;
}
private set
{
this.RaiseAndSetIfChanged(ref icon, new WeakReference<ImageSource>(value));
}
}
async void DownloadIcon()
{
Icon = await imageHelper.LoadImageFromUrlAsync(IconUrl, AppSettings.ThumbnailsFolder);
}
}
This one does but why is it even necessary to capture the context?
public class Album : AlbumBase
{
public Album()
{
this.synchronizationContext = SynchronizationContext.Current;
}
private SynchronizationContext synchronizationContext;
WeakReference<ImageSource> icon;
public ImageSource Icon
{
get
{
ImageSource result;
if (icon != null && icon.TryGetTarget(out result))
return result;
DownloadIcon();
return null;
}
private set
{
this.synchronizationContext.Post((x) =>
{
this.RaiseAndSetIfChanged(ref icon, new WeakReference<ImageSource>(value));
}, null);
}
}
async void DownloadIcon()
{
Icon = await imageHelper.LoadImageFromUrlAsync(IconUrl, AppSettings.ThumbnailsFolder);
}
}