Revisited: Guidance on Binding Media Resource Streams to XAML Controls

In my previous post Binding Media Resource Streams to XAML Controls, I discussed a way to use a value converter to get the read stream of the media resource of an a media link entry that is  bound to a control. The purpose of this was to bind a XAML Image control to a media resource stream. After having messed around with this for some time in a Window Phone 7 image-based application, I think that I can provide some further guidance on this scenario.

Two Possible Approaches

As I discussed previously, there are essentially two ways to do this…

Define an Extension Property that Returns the Stream URI

Creating an extension property on the client data class that is the media link entry enables you to call GetReadStreamUri in the property getter, like this:

public partial class PhotoInfo
{
// Returns the media resource URI for binding.
public Uri StreamUri
{
get
{
// Get the URI for the media resource stream.
return App.ViewModel.GetReadStreamUri(this);
}
}
}

The GetReadStreamUri method in the view model (this is from a Windows Phone app) simply calls into the GetReadStreamUri method in the DataServiceContext. And, the XAML (fragment) looks like this:

<Image Source="{Binding Path=StreamUri, Mode=OneWay}"
Height="100" Width="130" />

This enables you to return an image URI for binding…perfect.

Create a Value Converter that Returns the Stream URI

A value converter can also be called during binding, which can also call GetReadStreamUri to return a URI, like this:

public class StreamUriConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
// Return the URI of the media resource stream for binding.
return App.ViewModel.GetReadStreamUri(value);
}

    public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}

This example is also from a Windows Phone app, hence the view model again. In this case, the XAML is a bit more complicated, which the XAML looking like this:

<StackPanel.Resources>
<converter:StreamUriConverter x:Key="getStreamUri" />
</StackPanel.Resources>
<Image Source="{Binding Converter={StaticResource getStreamUri}}"
Height="75" Width="50" />

This also returns the URI of an image for binding.

Pros and Cons: The Guidance

First off, let me say that if you have a read-only data service where you only query and don’t send POST requests to insert new entities, you should probably use the extension property approach. It’s clean and much simpler to implement. Having said that, when you need to insert new media link entries into the data service, things get a bit more complicated. This scenario is what led me to originally explore using value converters, but even this approach has its limitations. So here goes…

 

Extension Property

Value Converter

Pros

This is a  no-brainer to implement with a read-only service. Also, because the URI is returned by a property of an entity that implements INotifyPropertyChanged, changes to the URI can be reported so that the image can be is updated even after binding has occurred. For example, I added an extension method on the PhotoInfo type that, when called, reports the change in the StreamUri extension property. This is useful when you don’t yet have the URI of the media resource because the data service hasn’t created it yet, as in the POST request to create a new media resource. By not adding a new property to the entity definition on the client, you can send insert POST requests directly to the data service without modifying the XML in the payload. I also found it easier to also much easier to debug a value converter as you can set a breakpoint right in the

Cons

The data service cannot handle requests that contain extra properties that are not known on to the service, so it fails to insert new media link entries on POST requests. The workaround for this is to handle the WritingEntity event and remove the extension property, as Phani describes in his blog post Customizing Serialization of Entities in the ADO.NET Data Services Client Library. It’s more difficult to debug a property (Path) binding than a value converter. The converter is only accessed when the collection is bound to the control.  This means that when a new media link entry is added to the binding collection on the client but before the media resource has been created in the data service, there is no way to report this change to the bound UI element. It seems like you must rebind the entire collection to be able to correctly bind the new media resource, which also reloads all the  media resources for all entries in the collection.

This general guidance applies when binding media resources to all XAML-based client applications. However, things get even more interesting in the Windows Phone platform for a couple of reasons. Stay tuned…I will cover this shortly in a subsequent post.