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

Advertisements

2 thoughts on “RIA services and combobox lookups with Async CTP

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s