This is a migrated thread and some comments may be shown as answers.

How To: Silverlight grid hierarchy load on demand using MVVM and RIA services

10 Answers 301 Views
GridView
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Richard Harrigan
Top achievements
Rank 1
Richard Harrigan asked on 10 Jul 2010, 08:20 PM
hI

I have the Silverlight grid hierarchy load on demand using MVVM and RIA services  example working.  I updated it to work with Silverlight and .Net Frameworks 4.0 with a few small changes (none to the xaml).  Assuming that you had the product table in in the DataContext how would you add the ProductName and ProductID to a ComboBox column in the details row and display the correct  product name for the details ProductID field?  I added the ComboBox column to the xaml and the Product column shows up but it did not bind to the product data.  I retrieved the product data at startup time and it is available but I can't seem to bind to it.

Thanks
Rich

10 Answers, 1 is accepted

Sort by
0
Richard Harrigan
Top achievements
Rank 1
answered on 14 Jul 2010, 05:54 PM
Hi,

I tried the following but the binding to Products does not happen.  Any thoughts on this?

Thanks
Rich

Added to DataContext class

public partial class Product

{

        Boolean productsLoaded = false;

        public IEnumerable<Product> Products

        {

            get

            {

                if (!productsLoaded)

                {

                    MyDataContext.DomainContext.Load(MyDataContext.DomainContext.GetProductsQuery());

                    productsLoaded = true;

                }

                return MyDataContext.DomainContext.Products;

            }

    }

Added to MainPage.xaml

 

                            <DataTemplate>

                                <telerik:RadGridView IsReadOnly="False" ShowGroupPanel="False" AutoGenerateColumns="False"

                                                     SelectionChanged="RadGridViewDetail_SelectionChanged"

                                                     KeyDown="RadGridViewDetail_KeyDown"

                                                     ItemsSource="{Binding Details}">

                                    <telerik:RadGridView.Columns>

                                        <telerik:GridViewDataColumn Header="Unit Price" DataMemberBinding="{Binding UnitPrice}" />

                                        <telerik:GridViewDataColumn Header="Quantity" DataMemberBinding="{Binding Quantity}" />

                                        <telerik:GridViewDataColumn Header="Discount" DataMemberBinding="{Binding Discount}" />

                                        <telerik:GridViewComboBoxColumn

                                            Header="Product Name"

                                            SelectedValueMemberPath="ProductID"

                                            DisplayMemberPath="ProductName"

                                            ItemsSource="{Binding Products}"

                                            DataMemberBinding="{Binding ProductID}"/>

                                    </telerik:RadGridView.Columns>

                                </telerik:RadGridView>

                            </DataTemplate>

0
Maya
Telerik team
answered on 15 Jul 2010, 09:36 AM
Hi Richard Harrigan,

Firstly, please accept my apologies  for the late response.
The issue you encountered can be resolved by setting ItemsSourceBinding instead of ItemsSource. Thus the in the definition of your GridViewComboBoxColumn would be:

<telerik:GridViewComboBoxColumn
         Header="Product Name"
         SelectedValueMemberPath="ProductID"
         DisplayMemberPath="ProductName"
         ItemsSourceBinding="{Binding Products}"
         DataMemberBinding="{Binding ProductID}"/>

I hope that helps.

Best wishes,
Maya
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Richard Harrigan
Top achievements
Rank 1
answered on 15 Jul 2010, 09:32 PM
Hi Maya,

I tried it and got the same result.  Could you please try and modify your original example and see if you can get it to work.  I hit the wall on this.  ItemsSourceBinding 'AllProducts' does not bind to MyDataContext.AllProducts. Attached is my code for mainpage.xaml, mainpage.xaml.cs and mainpage.xaml.  See my minimal changes in bold Red.

Thanks
Rich

MainPage.xaml.cs

public partial class MainPage : UserControl

    {

 

      

        public MainPage()

        {

            InitializeComponent();

            DataContext = new MyDataContext(); 

        }

       

        private void Submit_Click(object sender, RoutedEventArgs e)

        {

            // result1 and result2 both contain all products...Just checking

            var result1 = ((MyDataContext)DataContext).AllProducts;

            var result2 = MyDataContext.DomainContext.Products;

 

            if (MyDataContext.DomainContext.HasChanges)

            {

                MyDataContext.DomainContext.SubmitChanges();

            }

        }

    }

 

MyDataContext.cs

public class MyDataContext

    {

        static NWindContext _domainContext;

        public static NWindContext DomainContext

        {

            get

            {

                if (_domainContext == null)

                {

                    _domainContext = new NWindContext();

                  _domainContext.Load(_domainContext.GetProductsQuery());

                }

                return _domainContext;

            }

        }

 

        Boolean customersLoaded = false;

        public IEnumerable<Customer> Customers

        {

            get

            {

                if (!customersLoaded)

                {

                    DomainContext.Load(DomainContext.GetCustomersQuery());

                    customersLoaded = true;

                }

              

                return DomainContext.Customers;

            }

        }

 

        public IEnumerable<Product> AllProducts

       {

            get

            {

                return MyDataContext.DomainContext.Products;

            }

       }

    }

 

    public partial class Customer

    {

        Boolean ordersLoaded = false;

        public IEnumerable<Order> CustomerOrders

        {

            get

            {

                if (!ordersLoaded)

                {

                    MyDataContext.DomainContext.Load<Order>(MyDataContext.DomainContext.GetCustomerOrdersQuery(CustomerID));

                    ordersLoaded = true;

                }

                return MyDataContext.DomainContext.Orders;

            }

        }

    }

 

    public partial class Order

    {

        Boolean detailsLoaded = false;

        public IEnumerable<Order_Detail> Details

        {

            get

            {

                if (!detailsLoaded)

                {

                    MyDataContext.DomainContext.Load<Order_Detail>(MyDataContext.DomainContext.GetOrderDetailsQuery(OrderID));

                    detailsLoaded = true;

                }

                return MyDataContext.DomainContext.Order_Details;

            }

        }

    }

 

 

 

MainPage.xaml

<UserControl x:Class="TelerikMVVC2.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"

    xmlns:viewModel="clr-namespace:TelerikMVVC2.Web"

    xmlns:telerik="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.GridView"

    mc:Ignorable="d"

    d:DesignHeight="400" d:DesignWidth="600">

   

    <Grid x:Name="LayoutRoot" Background="White">

        <Grid.RowDefinitions>

            <RowDefinition Height ="30" />

            <RowDefinition Height ="*" />

            <RowDefinition Height ="Auto" />

        </Grid.RowDefinitions>

        <Button Grid.Row="0" Content="Submit" Click="Submit_Click"/>

        <telerik:RadGridView Grid.Row="1" Name="RadGridView1" 

                             IsReadOnly="false"

                             ShowGroupPanel="False"

                             CanUserFreezeColumns="False"

                             IsFilteringAllowed="False"

                             AutoGenerateColumns="False"

                             ItemsSource="{Binding PagedSource, ElementName=radDataPager1}">

            <telerik:RadGridView.ChildTableDefinitions>

                <telerik:GridViewTableDefinition />

            </telerik:RadGridView.ChildTableDefinitions>

            <telerik:RadGridView.Columns>

                <telerik:GridViewDataColumn Header="Customer ID" DataMemberBinding="{Binding CustomerID}" />

                <telerik:GridViewDataColumn Header="Company Name" DataMemberBinding="{Binding CompanyName}" />

                <telerik:GridViewDataColumn Header="Contact Name" DataMemberBinding="{Binding ContactName}" />

                <telerik:GridViewDataColumn Header="City" DataMemberBinding="{Binding City}" />

                <telerik:GridViewDataColumn Header="Country" DataMemberBinding="{Binding Country}" />

            </telerik:RadGridView.Columns>

            <telerik:RadGridView.HierarchyChildTemplate>

                <DataTemplate>

                    <telerik:RadGridView IsReadOnly="False" ShowGroupPanel="true" AutoGenerateColumns="False"   ItemsSource="{Binding  CustomerOrders}">

                        <telerik:RadGridView.ChildTableDefinitions>

                            <telerik:GridViewTableDefinition />

                        </telerik:RadGridView.ChildTableDefinitions>

                        <telerik:RadGridView.Columns>

                            <telerik:GridViewDataColumn Header="Order ID" DataMemberBinding="{Binding OrderID}" />

                            <telerik:GridViewDataColumn Header="Order Date" DataMemberBinding="{Binding OrderDate}" />

                        </telerik:RadGridView.Columns>

                        <telerik:RadGridView.HierarchyChildTemplate>

                            <DataTemplate>

                                <telerik:RadGridView IsReadOnly="False" ShowGroupPanel="False" AutoGenerateColumns="False"

                                                     ItemsSource="{Binding Details}">

                                    <telerik:RadGridView.Columns>

                                        <telerik:GridViewDataColumn Header="Unit Price" DataMemberBinding="{Binding UnitPrice}" />

                                        <telerik:GridViewDataColumn Header="Quantity" DataMemberBinding="{Binding Quantity}" />

                                        <telerik:GridViewDataColumn Header="Discount" DataMemberBinding="{Binding Discount}" />

                                    <telerik:GridViewComboBoxColumn

                                         Header="Product Name"

                                         SelectedValueMemberPath="ProductID"

                                         DisplayMemberPath="ProductName"

                                         ItemsSourceBinding="{Binding AllProducts}"

                                         DataMemberBinding="{Binding ProductID}"/>

                                    </telerik:RadGridView.Columns>

                                </telerik:RadGridView>

                            </DataTemplate>

                        </telerik:RadGridView.HierarchyChildTemplate>

                    </telerik:RadGridView>

                </DataTemplate>

            </telerik:RadGridView.HierarchyChildTemplate>

        </telerik:RadGridView>

      

        <telerik:RadDataPager Grid.Row="2"

               x:Name="radDataPager1"

               PageSize="20"

               DisplayMode="All"

               Source="{Binding Customers}"

               IsTotalItemCountFixed="True"/>

    </Grid>

</UserControl>

 

0
Tyree
Top achievements
Rank 2
answered on 16 Jul 2010, 01:53 PM
Have you checked your binding errors? In the immediate window?
0
Richard Harrigan
Top achievements
Rank 1
answered on 16 Jul 2010, 05:27 PM

How do you test xaml binding in immed window?

For your consideration:
Many enterprise databases are in third normal form and therefore the frequent need to handle Foreign Key relationships.  It would be very helpful to me and I expect many other developers to have a Hiarchtical RadGridView example using the Northwind database that contains Customer, Order and Order_Details tables containing a combobox column in the Order_Details row with the ProductName  from the Products table.  Since this example exists without the Product table I'm hoping it would not take to long to update the example including the Product table. 

http://blogs.telerik.com/Libraries/Vladimir_Enchev/SilverlightGridHierarchyUsingMVVMAndServices.sflb?download=true

Additional nice to have

Insert and delete keys functioning at all row levels
Upgrade the example to Silverlight 4.0 and .NET Frameworks 4.0

Thanks
Rich

0
Maya
Telerik team
answered on 19 Jul 2010, 09:05 AM
Hello Richard Harrigan,

Thank you for your feedback! We would definitely consider updating the blog post so that it meets more requirements.  
As for the issue with the binding of the ComboBoxColumn, the problem comes from the fact that the ItemsSource of the last grid is set to "Details", but there is no property "Products" in the Order_Details class. What you can do in this case is to define the ItemsSource of the ComboBoxColumn during the DataLoaded event of the grid and set it to the property Products of the Product class. For instance:

private void OrderDetailsGrid_DataLoading(object sender, Telerik.Windows.Controls.GridView.GridViewDataLoadingEventArgs e)
{
   RadGridView orderDetailsGrid = sender as RadGridView;
   GridViewComboBoxColumn comboColumn = new GridViewComboBoxColumn();
   comboColumn.Header = "Product Name";
   comboColumn.SelectedValueMemberPath = "ProductID";
   comboColumn.DisplayMemberPath = "ProductName";
   comboColumn.DataMemberBinding = new Binding("ProductID");
   comboColumn.ItemsSource = MyDataContext.DomainContext.Products;
   MyDataContext.DomainContext.Load(MyDataContext.DomainContext.GetProductsQuery());
 
  orderDetailsGrid.Columns.Add(comboColumn);                               
}

I am sending you the sample project so that you can use it as a reference.


Greetings,
Maya
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Richard Harrigan
Top achievements
Rank 1
answered on 19 Jul 2010, 10:20 PM
Thanks, that worked 99%.

When I expanded the first customer and first order the Product name field in each order detail row was blank.  When I clicked on the product name field the product name showed up.  All other detail rows when expanded were correct.  Since you explained how it works I eliminated the load event and put the combobox back in the xaml and used a converter to load the Product info.   That took care of the above mentioned blank product name field.

One thing I noticed is that when I try to filter on the combo box I get a list of Product ID's instead of Product Names.  Can  I change that behavior?

I also tried to use commands as shown in the  on-line Commands example. I could not get it to work. I did try

MyDataContext

 

 

.DomainContext.SubmitChanges(); and that worked fine.  I think I copied everything correctly from the example and don't think I missed anything.  Is there something else I need to do or is it a RIA thing???

 


Thanks
Rich
0
Maya
Telerik team
answered on 22 Jul 2010, 03:13 PM
Hello Richard Harrigan,

Indeed the values shown in the filter of the GridViewComboBoxColumn are the ProductID-s and for the time being this is the default behavior. However, in order to change it, you may use one of the two possible workarounds. 
The first one is explained in details in this blog post.
The second one is to make the filter show the ProductName-s during the DistinctValuesLoading event, but to make it operate with the ProductID-s so that it can do its job - filtering.

private void OrderDetailsGrid_DistinctValuesLoading(object sender, Telerik.Windows.Controls.GridView.GridViewDistinctValuesLoadingEventArgs e)
{
  e.ItemsSource = MyDataContext.DomainContext.Products.Select(p =>                p.ProductName);
}
 
private void OrderDetailsGrid_Filtering(object sender, Telerik.Windows.Controls.GridView.GridViewFilteringEventArgs e)
{
  foreach (Telerik.Windows.Data.FilterDescriptor fd in e.Added)
  {
     var product = MyDataContext.DomainContext.Products.Where(p => p.ProductName ==  fd.Value).FirstOrDefault();
     if(product != null)
     {
        fd.Value = product.ProductID;
     }             
  }
}

However, in this scenario the lower part of the Filter with the Operator (Is Equal To, Is Less Than, Or, etc.) will not work. We would introduce a new property ShowFieldFilters that will enable you to collapse that part of the filter. This will be available in our latest internal build this Friday.
Adding a Filter specified for the GridViewComboBoxColumn is in our to-do list and we are working on its development.


Best wishes,
Maya
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Richard Harrigan
Top achievements
Rank 1
answered on 22 Jul 2010, 04:11 PM
Hi,

Filtering GridViewComboBoxColumn in RadGridView for WPF.  Does the code also work for Silverlight?  Are the internal builds available and if so how do I get access.

Thanks
Rich
0
Maya
Telerik team
answered on 22 Jul 2010, 04:38 PM
Hello Richard Harrigan,

 
The second proposed solution is for Silverlight and it is developed and tested on the sample project I have sent to you previously. The workaround exposed in the blog post is also applicable for Silverlight.
You can download our latest internal builds from: Your Account ->Free Trials -> RadControls for Silverlight -> Latest Internal Builds (Trial). 

Best wishes,
Maya
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
Tags
GridView
Asked by
Richard Harrigan
Top achievements
Rank 1
Answers by
Richard Harrigan
Top achievements
Rank 1
Maya
Telerik team
Tyree
Top achievements
Rank 2
Share this question
or