DataGrid and “No Records Found” message

Here is one way to display a message when we dont have any data returned

1. Grab the Template of the DataGrid from Blend

2. Modify the Template. All we do is find the RowsPresenter line
<sdk:DataGridRowsPresenter x:Name=”RowsPresenter” Grid.ColumnSpan=”2″ Grid.Row=”1″/>
and move it inside a Grid element, we add in the template in the same place.
The Grid has a TextBlock to show the message and Visibility is controlled by a Converter

Here is the relevant part of the Template

<sdk:DataGridColumnHeader x:Name=”TopLeftCornerHeader” Template=”{StaticResource TopLeftHeaderTemplate}” Width=”22″/>
<sdk:DataGridColumnHeadersPresenter x:Name=”ColumnHeadersPresenter” Grid.Column=”1″/>
<sdk:DataGridColumnHeader x:Name=”TopRightCornerHeader” Grid.Column=”2″ Template=”{StaticResource TopRightHeaderTemplate}”/>
<Rectangle x:Name=”ColumnHeadersAndRowsSeparator” Grid.ColumnSpan=”3″ Fill=”#FFC9CACA” Height=”1″ StrokeThickness=”1″ VerticalAlignment=”Bottom” Width=”Auto”/>
<!–<sdk:DataGridRowsPresenter x:Name=”RowsPresenter” Grid.ColumnSpan=”2″ Grid.Row=”1″/>–>
<Grid Grid.ColumnSpan=”2″ Grid.Row=”1″ >
<sdk:DataGridRowsPresenter x:Name=”RowsPresenter”/>
<TextBlock Text=”No Records found”
Visibility=”{Binding ElementName=RowsPresenter, Path=Children.Count, Converter={StaticResource noRecordsConverter}}”
HorizontalAlignment=”Center” VerticalAlignment=”Center”
FontSize=”12″/>
</Grid>

<Rectangle x:Name=”BottomRightCorner” Grid.Column=”2″ Fill=”#FFE9EEF4″ Grid.Row=”2″/>
<Rectangle x:Name=”BottomLeftCorner” Grid.ColumnSpan=”2″ Fill=”#FFE9EEF4″ Grid.Row=”2″/>
<ScrollBar x:Name=”VerticalScrollbar” Grid.Column=”2″ Margin=”0,-1,-1,-1″ Orientation=”Vertical” Grid.Row=”1″ Width=”18″/>

And the Converter

public class NoRecordsConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value.ToString() == “0” ? Visibility.Visible : Visibility.Collapsed;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}

EntityFramework 4, code first and RIA Services

I was looking at EF4 and code first CTP5 and wanted to see how that works with RIA Services. So I took John Papa’s sample from PDC10 and started converting that to use code first.

Here are the steps

1.Becasue we already have a database and want to generate the classes quickly Open the EDMX file  right click and add code generation item and select “ADO.NET DbContext Generator” . this will generate the model classes and the context

2.After the classes are generated we will have a BookClubEntities class. we have to change the connectingstring to go directly to database

the modified connection string in Web.Config looks like this

<add name=”BookClubEntities” connectionString=”Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\BookClub.mdf;Integrated Security=True;User Instance=True;MultipleActiveResultSets=True” providerName=”System.Data.SqlClient” />

3. we need to override OnModelCreating to add our mapping. All of them are starightforward except for ImageSource column in the Book class. We dont have that in the Database, so we ignore it. Here is the context class after mapping

public partial class BookClubEntities : DbContext
{
public BookClubEntities()
: base(“name=BookClubEntities”)
{

}

public DbSet<BookOfDay> BookOfDays { get; set; }
public DbSet<Book> Books { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Checkout> Checkouts { get; set; }
public DbSet<Member> Members { get; set; }
public DbSet<Request> Requests { get; set; }

protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

//books
modelBuilder.Entity<Book>().Ignore(x => x.ImageSource);
modelBuilder.Entity<Book>().HasMany(x => x.BookOfDays).WithRequired(x => x.Book).HasForeignKey(x => x.BookID);
modelBuilder.Entity<Book>().HasMany(x => x.Checkouts).WithRequired(x => x.Book).HasForeignKey(x => x.BookID);
modelBuilder.Entity<Book>().HasMany(x => x.Requests).WithRequired(x => x.Book).HasForeignKey(x => x.BookID);

modelBuilder.Entity<Category>().HasMany(x => x.Books).WithRequired(x => x.Category).HasForeignKey(x => x.CategoryID);

modelBuilder.Entity<Member>().HasMany(x => x.Books).WithRequired(x => x.Member).HasForeignKey(x => x.MemberID);
modelBuilder.Entity<Member>().HasMany(x => x.Checkouts).WithRequired(x => x.Member).HasForeignKey(x => x.MemberID);
modelBuilder.Entity<Member>().HasMany(x => x.Requests).WithRequired(x => x.Member).HasForeignKey(x => x.MemberID);

modelBuilder.Entity<Checkout>().HasMany(x => x.Requests).WithRequired(x => x.Checkout).HasForeignKey(x => x.CheckoutID);

}
}

3. We have to map the classes to Tables, whereever the tablename differs from the class name we add “Table” attribute on the class for mapping and add “Key” attributes on the primary columns

4. We add Association Attribute on  all the properties that we want to include in our results.

5. Add the DbContextExtensions file. it contains useful extension methods. (I got the code from the EF forums posted by a user and refined by person from MSFT)

6. Last but not least change the code in the actual service to inherit from DomainService and modify the queries to go against the context we created and not ObjectContext

If all the mappings are right, we should have the application working again without the edmx file.

You can download the files changed or added here. This zip file has only the relevant files, not the whole application.

Prism 4 – Silverlight and Custom Commands

Silverlight 4 includes commanding support for ButtonBase classes, but for anything else we would need to write a little bit of code.

There is a nice section here on how to extend this to other situations. Here is a quick sample on how to create command support for MouseLeftButtonDown on an UIElement. You can download the code from here.

Here is how we can use the Command behavior we create for invoking a command on the mouseleftbutton up event

<UserControl x:Class=”SLPrismCustomCommands.MainPage”
    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation
    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml
    xmlns:d=”http://schemas.microsoft.com/expression/blend/2008
    xmlns:mc=”http://schemas.openxmlformats.org/markup-compatibility/2006
    mc:Ignorable=”d”
             xmlns:local=”clr-namespace:SLPrismCustomCommands”
    d:DesignHeight=”300″ d:DesignWidth=”400″>

    <Grid x:Name=”LayoutRoot” Background=”White”>
        <Ellipse Fill=”Green” Width=”20″ Height=”20″
                 local:Click.CommandParameter=”{Binding RelativeSource={RelativeSource Self}}”
                 local:Click.Command=”{Binding MyCommand}”/>
    </Grid>
</UserControl>

The following would create a behavior

  public class MouseLeftButtonDownBehavior : CommandBehaviorBase<UIElement>
    {
        public MouseLeftButtonDownBehavior(UIElement obj)
            : base(obj)
        {
            if (obj == null) throw new System.ArgumentNullException(“object cannot be null”);
            obj.MouseLeftButtonDown += new MouseButtonEventHandler(OnMouseButton);
        }

        private void OnMouseButton(object sender, System.Windows.RoutedEventArgs e)
        {
            ExecuteCommand();
        }
    }

Here is the class for the Attached properties

public static class Click
    {
        private static readonly DependencyProperty ClickCommandBehaviorProperty = DependencyProperty.RegisterAttached(
            “ClickCommandBehavior”,
            typeof(MouseLeftButtonDownBehavior),
            typeof(Click),
            null);
        /// <summary>
        /// Command to execute on click event.
        /// </summary>
        public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached(
            “Command”,
            typeof(ICommand),
            typeof(Click),
            new PropertyMetadata(OnSetCommandCallback));

        /// <summary>
        /// Command parameter to supply on command execution.
        /// </summary>
        public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.RegisterAttached(
            “CommandParameter”,
            typeof(object),
            typeof(Click),
            new PropertyMetadata(OnSetCommandParameterCallback));
        /// <summary>
        /// Sets the <see cref=”ICommand”/> to execute on the click event.
        /// </summary>
        /// <param name=”buttonBase”>UIElement dependency object to attach command</param>
        /// <param name=”command”>Command to attach</param>       
        public static void SetCommand(UIElement element, ICommand command)
        {
            if (element == null) throw new System.ArgumentNullException(“element”);
            element.SetValue(CommandProperty, command);
        }

        /// <summary>
        /// Retrieves the <see cref=”ICommand”/> attached to the <see cref=”ButtonBase”/>.
        /// </summary>
        /// <param name=”buttonBase”>ButtonBase containing the Command dependency property</param>
        /// <returns>The value of the command attached</returns>       
        public static ICommand GetCommand(UIElement element)
        {
            if (element == null) throw new System.ArgumentNullException(“element”);
            return element.GetValue(CommandProperty) as ICommand;
        }

        /// <summary>
        /// Sets the value for the CommandParameter attached property on the provided <see cref=”ButtonBase”/>.
        /// </summary>
        /// <param name=”buttonBase”>ButtonBase to attach CommandParameter</param>
        /// <param name=”parameter”>Parameter value to attach</param>       
        public static void SetCommandParameter(UIElement element, object parameter)
        {
            if (element == null) throw new System.ArgumentNullException(“element”);
            element.SetValue(CommandParameterProperty, parameter);
        }

        /// <summary>
        /// Gets the value in CommandParameter attached property on the provided <see cref=”ButtonBase”/>
        /// </summary>
        /// <param name=”buttonBase”>ButtonBase that has the CommandParameter</param>
        /// <returns>The value of the property</returns>       
        public static object GetCommandParameter(UIElement element)
        {
            if (element == null) throw new System.ArgumentNullException(“element”);
            return element.GetValue(CommandParameterProperty);
        }

        private static void OnSetCommandCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            UIElement element = dependencyObject as UIElement;
            if (element != null)
            {
                MouseLeftButtonDownBehavior behavior = GetOrCreateBehavior(element);
                behavior.Command = e.NewValue as ICommand;
            }
        }

        private static void OnSetCommandParameterCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            UIElement element = dependencyObject as UIElement;
            if (element != null)
            {
                MouseLeftButtonDownBehavior behavior = GetOrCreateBehavior(element);
                behavior.CommandParameter = e.NewValue;
            }
        }

        private static MouseLeftButtonDownBehavior GetOrCreateBehavior(UIElement element)
        {
            MouseLeftButtonDownBehavior behavior = element.GetValue(ClickCommandBehaviorProperty) as MouseLeftButtonDownBehavior;
            if (behavior == null)
            {
                behavior = new MouseLeftButtonDownBehavior(element);
                element.SetValue(ClickCommandBehaviorProperty, behavior);
            }

            return behavior;
        }
    }
and here is the code for the CommandBehaviorBase

public class CommandBehaviorBase<T> where T : UIElement
    {
        private ICommand command;
        private object commandParameter;
        private readonly WeakReference targetObject;
        private readonly EventHandler commandCanExecuteChangedHandler;
        /// <summary>
        /// Constructor specifying the target object.
        /// </summary>
        /// <param name=”targetObject”>The target object the behavior is attached to.</param>
        public CommandBehaviorBase(T targetObject)
        {
            this.targetObject = new WeakReference(targetObject);

            // In Silverlight, unlike WPF, this is strictly not necessary since the Command properties
            // in Silverlight do not expect their CanExecuteChanged handlers to be weakly held,
            // but holding on to them in this manner should do no harm.
            this.commandCanExecuteChangedHandler = new EventHandler(this.CommandCanExecuteChanged);
        }

        /// <summary>
        /// Corresponding command to be execute and monitored for <see cref=”ICommand.CanExecuteChanged”/>
        /// </summary>
        public ICommand Command
        {
            get { return command; }
            set
            {
                if (this.command != null)
                {
                    this.command.CanExecuteChanged -= this.commandCanExecuteChangedHandler;
                }

                this.command = value;
                if (this.command != null)
                {
                    this.command.CanExecuteChanged += this.commandCanExecuteChangedHandler;
                    UpdateEnabledState();
                }
            }
        }

        /// <summary>
        /// The parameter to supply the command during execution
        /// </summary>
        public object CommandParameter
        {
            get { return this.commandParameter; }
            set
            {
                if (this.commandParameter != value)
                {
                    this.commandParameter = value;
                    this.UpdateEnabledState();
                }
            }
        }

        /// <summary>
        /// Object to which this behavior is attached.
        /// </summary>
        protected T TargetObject
        {
            get
            {
                return targetObject.Target as T;
            }
        }
        /// <summary>
        /// Updates the target object’s IsEnabled property based on the commands ability to execute.
        /// </summary>
        protected virtual void UpdateEnabledState()
        {
            if (TargetObject == null)
            {
                this.Command = null;
                this.CommandParameter = null;
            }
            else if (this.Command != null)
            {
                TargetObject.IsHitTestVisible = this.Command.CanExecute(this.CommandParameter);
            }
        }

        private void CommandCanExecuteChanged(object sender, EventArgs e)
        {
            this.UpdateEnabledState();
        }

        /// <summary>
        /// Executes the command, if it’s set, providing the <see cref=”CommandParameter”/>
        /// </summary>
        protected virtual void ExecuteCommand()
        {
            if (this.Command != null)
            {
                this.Command.Execute(this.CommandParameter);
            }
        }
    }

 

 

RIA services and combobox lookups with Async CTP

If we are editing data in a datagrid and have a few combobox columns, it will be difficult to know when the data is ready for all the comboboxes. The Async CTP that was released will help.

I got the extension method Kyle McClellan wrote in this post to consume LoadOperations as Tasks.
I had the following setup to display data from Products table in Northwind database in a Datagrid with Suppliers and categories as Comboboxes for editing.
          <sdk:DataGrid AutoGenerateColumns=”False” Name=”dataGrid1″ ItemsSource=”{Binding Products}”>
            <sdk:DataGrid.Columns>
                <sdk:DataGridTextColumn Header=”Name”  Binding=”{Binding ProductName}”/>
                <sdk:DataGridTemplateColumn Header=”Supplier”>
                    <sdk:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text=”{Binding Supplier.CompanyName}”/>
                        </DataTemplate>
                    </sdk:DataGridTemplateColumn.CellTemplate>
                    <sdk:DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate>
                                <ComboBox ItemsSource=”{Binding Source={StaticResource root}, Path=DataContext.Suppliers}” 
                                          SelectedValuePath=”SupplierID”
                                          DisplayMemberPath=”CompanyName”
                                          SelectedValue=”{Binding SupplierID, Mode=TwoWay}” />
                        </DataTemplate>
                    </sdk:DataGridTemplateColumn.CellEditingTemplate>
                </sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn Header=”Category”>
                    <sdk:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text=”{Binding Category.CategoryName}”/>
                        </DataTemplate>
                    </sdk:DataGridTemplateColumn.CellTemplate>
                    <sdk:DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate>
                                <ComboBox ItemsSource=”{Binding Source={StaticResource root}, Path=DataContext.Categories}” 
                                          SelectedValuePath=”CategoryID”
                                          DisplayMemberPath=”CategoryName”
                                          SelectedValue=”{Binding CategoryID, Mode=TwoWay}” />
                        </DataTemplate>
                    </sdk:DataGridTemplateColumn.CellEditingTemplate>
                </sdk:DataGridTemplateColumn>
                <sdk:DataGridTextColumn Header=”QuantityPerUnit”  Binding=”{Binding QuantityPerUnit}”/>
                <sdk:DataGridTextColumn Header=”UnitPrice”  Binding=”{Binding UnitPrice}”/>
            </sdk:DataGrid.Columns>
        </sdk:DataGrid>
       
The Domain service methods for getting categories and suppliers are going to return data after 5 and 3 sec.<
 public IQueryable<Category> GetCategories()
        {
            Thread.Sleep(5000);
            return this.ObjectContext.Categories;
        }

 public IQueryable<Supplier> GetSuppliers()
        {
            Thread.Sleep(3000);
            return this.ObjectContext.Suppliers;
        }

The Page is bound to instance of a ViewModel. If we use the GetData method to load the data, we can see that data is not loaded yet for the Categories and Suppliers columns. If we use GetDataAsync method to load the data, we are going to see the datagrid populated when all the related data is there.

 public class MainViewModel : INotifyPropertyChanged
    {
        public IEnumerable<Supplier> Suppliers { get; set; }
        public IEnumerable<Category> Categories { get; set; }
        public IEnumerable<Product> Products { get; set; }
        NorthwindDomainContext ctx = new NorthwindDomainContext();

        public MainViewModel()
        {
            //GetData();
            GetDataAsync();
        }

        async void GetDataAsync()
        {
            Task<LoadOperation<Product>> productTask = ctx.Load(ctx.GetProductsQuery()).AsTask();
            Task<LoadOperation<Category>> categoryTask = ctx.Load(ctx.GetCategoriesQuery()).AsTask();
            Task<LoadOperation<Supplier>> supplierTask = ctx.Load(ctx.GetSuppliersQuery()).AsTask();
            await TaskEx.WhenAll(productTask, categoryTask, supplierTask);
            Suppliers = supplierTask.Result.Entities;
            Products = productTask.Result.Entities;
            Categories = categoryTask.Result.Entities;

            NotifyPropertyChanged("Suppliers");
            NotifyPropertyChanged("Categories");
            NotifyPropertyChanged("Products");
        }

        void GetData()
        {
            ctx.Load<Product>(ctx.GetProductsQuery(), (lo) => { Products = lo.Entities; NotifyPropertyChanged("Products"); }, false);
            ctx.Load<Category>(ctx.GetCategoriesQuery(), (lo) => { Categories = lo.Entities; NotifyPropertyChanged("Categories"); }, false);
            ctx.Load<Supplier>(ctx.GetSuppliersQuery(), (lo) => { Suppliers = lo.Entities; NotifyPropertyChanged("Suppliers"); }, false);          
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this,
                    new PropertyChangedEventArgs(propertyName));
            }
        }

    }

you can download the code from here

WCF RIA Services and ComplexObjects

The release of the WCF RIA Services V1.0 SP1 Beta, added support for complex type members in entities and DomainService operations. Here is a quick walkthrough.

I started with Northwind database and customers table. I refactored some of the columns (Address,City,Region, PostalCode, Country) into a complex object called “AddressDetails” and updated the mappings like we see in the screenshot. Added a DomainService based on the model.

I added a Dataform in the Silverlight application like below

<toolkit:DataForm x:Name=”dataform1″ AutoEdit=”True” AutoCommit=”True”  
                          CommandButtonsVisibility=”All”  >
            <StackPanel>
                <toolkit:DataField Label=”CustomerId”>
                    <TextBox Text=”{Binding CustomerID, Mode=TwoWay}”/>
                </toolkit:DataField>
                <toolkit:DataField Label=”ContactName”>
                    <TextBox Text=”{Binding ContactName, Mode=TwoWay}”/>
                </toolkit:DataField>
                <toolkit:DataField Label=”ContactTitle”>
                    <TextBox Text=”{Binding ContactTitle, Mode=TwoWay}”/>
                </toolkit:DataField>
                <toolkit:DataField Label=”CompanyName”>
                    <TextBox Text=”{Binding CompanyName, Mode=TwoWay}”/>
                </toolkit:DataField>
                <toolkit:DataField Label=”Address”>
                    <TextBox Text=”{Binding AddressDetails.Address, Mode=TwoWay}”/>
                </toolkit:DataField>
                <toolkit:DataField Label=”City”>
                    <TextBox Text=”{Binding AddressDetails.City, Mode=TwoWay}”/>
                </toolkit:DataField>
                <toolkit:DataField Label=”PostalCode”>
                    <TextBox Text=”{Binding AddressDetails.PostalCode, Mode=TwoWay}”/>
                </toolkit:DataField>
                <toolkit:DataField Label=”Country”>
                    <TextBox Text=”{Binding AddressDetails.Country, Mode=TwoWay}”/>
                </toolkit:DataField>
            </StackPanel>   
        </toolkit:DataForm>
Here is the code behind.

public partial class MainPage : UserControl
    {
        DomainService1 ctx = new DomainService1();

        public MainPage()
        {
            InitializeComponent();

            this.DataContext = this;
            this.Loaded += new RoutedEventHandler(MainPage_Loaded);
            dataform1.EditEnded += new EventHandler<DataFormEditEndedEventArgs>(dataform1_EditEnded);
          
        }

        void dataform1_EditEnded(object sender, DataFormEditEndedEventArgs e)
        {           
            ctx.SubmitChanges();
        }
        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            LoadOperation<Customer> lo = ctx.Load<Customer>(ctx.GetCustomersQuery());
            lo.Completed += new EventHandler(lo_Completed);
        }

        void lo_Completed(object sender, EventArgs e)
        {
            dataform1.ItemsSource = (sender as LoadOperation<Customer>).Entities.ToList();
        }

    }

we can change data and click ok for the data to be saved. The Ok Button is not enabled, if the changes are made to the fields that are part of the complex object(“AddressDetails”). I tried to add a new customer. After filling in all the fields clicked “ok” button and got the error “AddressDetails is required”.  I added the following code to create a new instance of AddressDetails when a Customer is created
 public partial class Customer
    {
        partial void OnCreated()
        {
            this.AddressDetails = new AddressDetails();
          
        }             
    }

I did not get any error, but the new customer is not saved. The Context did not see any changes. so I had to explicitly add code to check the entitystate and add the object to the context for the new customer to be saved. I am not sure if I am missing something here.

 void dataform1_EditEnded(object sender, DataFormEditEndedEventArgs e)
        {
            if ((dataform1.CurrentItem as Customer).EntityState == EntityState.Detached)
                ctx.Customers.Add(dataform1.CurrentItem as Customer);
            ctx.SubmitChanges();
        }
We can also get the complex object by itself. I added the following code to get the AddressDetails for a given customer in the domainservice

  public AddressDetails GetCustomerAddressDetails(string customerId)
        {
            return this.ObjectContext.Customers.Where(x=>x.CustomerID == customerId).FirstOrDefault().AddressDetails;
        }

and call it like so from the client

ctx.GetCustomerAddressDetails(“ALFKI”, (io) => { AddressDetails details = io.Value; }, null);

The complexobject doesnt need to be based on an entity in the model, I added a customclass like below

    [Serializable()]
    [DataContract]
    public partial class CustomersSummary : ComplexObject
    {
        [Key]
        [DataMember]
        public string Country { get; set; }
        [DataMember]
        public int NumberOfCustomers { get; set; }
    }
wrote a method in the domainservice like below to return a list of the customobjects

  public IQueryable<CustomersSummary> GetCustomerSummary()
        {
            List<CustomersSummary> returnList=  this.ObjectContext.Customers.Where(c=>c.AddressDetails.Country !=null).GroupBy(x => x.AddressDetails.Country).Select(y => new CustomersSummary { Country = y.Key, NumberOfCustomers = y.Count() }).ToList();
            return returnList.AsQueryable();
        }

On the client the following code would get the list of customobjects.

ctx.Load<CustomersSummary>(ctx.GetCustomerSummaryQuery(), (lo) => { List<CustomersSummary> data = lo.Entities.ToList(); }, false);

Highlighting entire column in Datagrid

I came across this post on stackoverflow on highlighting an entire column when that column is sorted (clicked on header). The question was already answered. Here is another version. ItemsSource property need not be a PagedCollectionView in this version. The code need to be changed if there are any TemplateColumns defined.

using this behavior

 <sdk:DataGrid  x:Name=”datagrid1″  >
            <i:Interaction.Behaviors>
                <local:HiliteColumnBehavior/>
            </i:Interaction.Behaviors>
        </sdk:DataGrid>

Here is the behavior itself

 public class HiliteColumnBehavior : Behavior<DataGrid>
    {       
        bool isDragging = false;
        bool isDone = false;
        readonly SolidColorBrush hiliteColor = new SolidColorBrush(Colors.LightGray);
        readonly SolidColorBrush normalColor = new SolidColorBrush(Colors.White);
        DataGridColumnHeader currentSortColumnHeader;
        ScrollBar scrollbar;
        protected override void OnAttached()
        {
            base.OnAttached();
           
            AssociatedObject.ColumnHeaderDragStarted += new EventHandler<DragStartedEventArgs>(AssociatedObject_ColumnHeaderDragStarted);
            AssociatedObject.ColumnHeaderDragCompleted += new EventHandler<DragCompletedEventArgs>(AssociatedObject_ColumnHeaderDragCompleted);
            AssociatedObject.LayoutUpdated += new EventHandler(AssociatedObject_LayoutUpdated);
            AssociatedObject.SizeChanged += (s, e) => { Hilite(); };
        }

        DataGridColumnHeadersPresenter dchp;
        void AssociatedObject_LayoutUpdated(object sender, EventArgs e)
        {
            dchp = AssociatedObject.GetChildrenByType<DataGridColumnHeadersPresenter>().FirstOrDefault();
            if (dchp != null && !isDone) {
                foreach (DataGridColumnHeader dgch in dchp.Children)
                    dgch.AddHandler(DataGridColumnHeader.MouseLeftButtonUpEvent, new MouseButtonEventHandler(header_MouseLeftButtonUp), true);

                isDone = true;
            }
            if (scrollbar == null)
            {
                scrollbar = AssociatedObject.GetChildrenByType<ScrollBar>().FirstOrDefault();
                scrollbar.Scroll += new ScrollEventHandler(scrollbar_Scroll);
            }
               
        }

        void scrollbar_Scroll(object sender, ScrollEventArgs e)
        {
            if (e.ScrollEventType == ScrollEventType.EndScroll)
                Hilite();
        }

        void AssociatedObject_ColumnHeaderDragCompleted(object sender, DragCompletedEventArgs e)
        {
            isDragging = false;
        }

        void AssociatedObject_ColumnHeaderDragStarted(object sender, DragStartedEventArgs e)
        {
            isDragging = true;
        }

        void header_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            currentSortColumnHeader = sender as DataGridColumnHeader;
           
            if (!isDragging)
            {
                Hilite();
            }
           
        }

        private void Hilite()
        {
            if (currentSortColumnHeader == null)
                return;
            int columnIndex = dchp.Children.IndexOf(currentSortColumnHeader);
            List<DataGridRow> rows = AssociatedObject.GetChildrenByType<DataGridRow>();
            rows.ForEach(x => { x.GetChildrenByType<DataGridCell>().Where((y, i) => i == columnIndex).ToList().ForEach(z => z.Background = hiliteColor); });
            rows.ForEach(x => { x.GetChildrenByType<DataGridCell>().Where((y, i) => i != columnIndex).ToList().ForEach(z => z.Background = normalColor); });
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();

            foreach (DataGridColumnHeader dgch in dchp.Children)
                dgch.RemoveHandler(DataGridColumnHeader.MouseLeftButtonUpEvent, new MouseButtonEventHandler(header_MouseLeftButtonUp));

            if (scrollbar != null)
            {            
                scrollbar.Scroll -= new ScrollEventHandler(scrollbar_Scroll);
            }
        }
    }

    public static class Extensions
    {
        public static T FindParentOfType<T>(this FrameworkElement element)
        {
            if (element == null)
                return default(T);

            var parent = VisualTreeHelper.GetParent(element) as FrameworkElement;

            while (parent != null)
            {
                if (parent is T)
                    return (T)(object)parent;

                parent = VisualTreeHelper.GetParent(parent) as FrameworkElement;
            }
            return default(T);
        }

        // Methods
        public static List<T> GetChildrenByType<T>(this UIElement element) where T : UIElement
        {
            return element.GetChildrenByType<T>(null);
        }

        public static List<T> GetChildrenByType<T>(this UIElement element, Func<T, bool> condition) where T : UIElement
        {
            List<T> results = new List<T>();
            GetChildrenByType<T>(element, condition, results);
            return results;
        }

        private static void GetChildrenByType<T>(UIElement element, Func<T, bool> condition, List<T> results) where T : UIElement
        {
            if (element == null)
                return;
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
            {
                UIElement child = VisualTreeHelper.GetChild(element, i) as UIElement;
                if (child != null)
                {
                    T t = child as T;
                    if (t != null)
                    {
                        if (condition == null)
                        {
                            results.Add(t);
                        }
                        else if (condition(t))
                        {
                            results.Add(t);
                        }
                    }
                    GetChildrenByType<T>(child, condition, results);
                }
            }
        }

        public static bool HasChildrenByType<T>(this UIElement element, Func<T, bool> condition) where T : UIElement
        {
            return (element.GetChildrenByType<T>(condition).Count != 0);
        }
    }

StoredProcedures with multiple result sets and RIA Services

Here is one way we could work with StoredProcedures that return multiple results when using WCF RIA Services. I grabbed the code for EFExtensions and  was working with a model from MusicStoreSample

I created a simple procedure, which returns the artist details for the given Id and all the Albums for the Artist

create procedure [dbo].[GetArtistDetails](@artistId int) as

select * from Artist where ArtistId=@artistId                    
select * from album where ArtistId=@artistId                    
I extended the generated Entities class in the web project to add a method (followed the Sample in the  EFExtensions sample project).

public partial class MusicStoreEntities : ObjectContext
    {
        private static readonly Materializer<Artist> s_artistMaterializer = new Materializer<Artist>();
        private static readonly Materializer<Album> s_albumMaterializer = new Materializer<Album>();
        public Artist GetArtistAndRelatedAlbums(int artistId)
        {
            DbCommand command = this.CreateStoreCommand(“GetArtistDetails”, CommandType.StoredProcedure, new SqlParameter(“artistId”, artistId));
            Artist artist;

            using (command.Connection.CreateConnectionScope())
            using (DbDataReader reader = command.ExecuteReader())
            {
                // first result set includes the category
                artist = s_artistMaterializer
                    .Materialize(reader)
                    .Bind(this.Artists)
                    .SingleOrDefault();

                // second result set includes the related products
                if (null != artist && reader.NextResult())
                {
                    artist.Albums.Attach(s_albumMaterializer
                        .Materialize(reader)
                        .Bind(this.Albums));
                }
            }

            return artist;
        }
    }

In the DomainService class I created based on the MusicStoreEntities, I added the following method which calls the method we created above

  public Artist GetArtistAndRelatedAlbums(int artistId)
        {
            return this.ObjectContext.GetArtistAndRelatedAlbums(artistId);
        }

In the Generated MetaData class, Added [Include] attribute on Albums property

 public partial class Artist
    {
      
        internal sealed class ArtistMetadata
        {

            // Metadata classes are not meant to be instantiated.
            private ArtistMetadata()
            {
            }

            [Include]
            public EntityCollection<Album> Albums { get; set; }

            public int ArtistId { get; set; }

            public string Name { get; set; }
        }
    }

In the client project, we could write small bit of code to test and see, we get Artist Details along with all the Albums for the artist

Artist artist = null;
MusicStoreDomainContext _ctx = new MusicStoreDomainContext();           
            _ctx.Load<Artist>(_ctx.GetArtistAndRelatedAlbumsQuery(22), (lo) => {
                artist = lo.Entities.FirstOrDefault();
                }, null);                                    
            }, false);