While the DomainDataSource is most often used for loading entire sets of records, it can also be used for loading a single record result.  This is a topic I’ve seen a few people talk about, assuming it’s a difficult thing to do, and even creating solutions for a problem that doesn’t exist.  I want to dispel the myth here: DomainDataSource can in fact be used to easily bind to a single record result.

Let’s create a DomainService that has a method to get the most recent error from the AdventureWorks database:

 
namespace SingleResult.Web
{
    using System.Linq;
    using System.Web.DomainServices.LinqToEntities;
    using System.Web.Ria;
 
    [EnableClientAccess()]
    public class ErrorLogService : LinqToEntitiesDomainService<AdventureWorksEntities>
    {
        public ErrorLog GetLastError()
        {
            return this.Context.ErrorLog.OrderByDescending(e => e.ErrorTime).FirstOrDefault();
        }
    }
}
 
 

Now let’s create a XAML page that shows the details of the most recent error, using DomainDataSource:

<UserControl x:Class="SingleResult.MainPage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:my="clr-namespace:SingleResult.Web"
             xmlns:dds="clr-namespace:System.Windows.Controls;assembly=System.Windows.Ria.Controls">
    <StackPanel x:Name="LayoutRoot">
        <dds:DomainDataSource x:Name="errorSource" QueryName="GetLastError">
            <dds:DomainDataSource.DomainContext>
                <my:ErrorLogContext />
            </dds:DomainDataSource.DomainContext>
        </dds:DomainDataSource>
        
        <TextBox Width="150" Text="{Binding Path=Data.ErrorNumber, ElementName=errorSource}" />
        <TextBox Width="150" Text="{Binding Path=Data.ErrorSeverity, ElementName=errorSource}" />
        <TextBox Width="150" Text="{Binding Path=Data.UserName, ElementName=errorSource}" />
        <TextBox Width="150" Text="{Binding Path=Data.ErrorState, ElementName=errorSource}" />
        <TextBox Width="150" Text="{Binding Path=Data.ErrorProcedure, ElementName=errorSource}" />
        <TextBox Width="150" Text="{Binding Path=Data.ErrorLine, ElementName=errorSource}" />
        <TextBox Width="150" Text="{Binding Path=Data.ErrorMessage, ElementName=errorSource}" />
    </StackPanel>
</UserControl>

Bam, Bob’s your Uncle!  In other words, that’s it; it works.

The reason this works so easily is that the Silverlight Binding identifies that the Data property from the binding implements ICollectionView.  When it can’t find the nested property on Data, it then infers Data.CurrentItem, and finds the child properties from that.

Strangely enough, with the RIA Services July 2009 Preview, if you tried to put Data.CurrentItem in yourself, it would fail.  This was a joint bug between Silverlight and RIA Services, and it will be fixed in the next release of each.

Happy binding!