Thursday 19 May 2011

Telerik Silverlight RadGridView ComboBox Column data binding problem

I am using telerik Silverlight GridView control, one of the cool features is that it has a ComboBox Column, which can enable the developer embad a ComboBox in GridView's column
like this:









While of course you can embad such a ComboBox in regular DataGridView(i mean, in micorsoft silverlight toolkit), but Telerik makes things much eazier..

But if you try to bind data through ViewMode to the ComboBox Column of the RadGridView, you will encounter some serious problem.

Let's design a lightweight project to test this cool features of Telerik(this has be existing for long time, I don;t know why Telerik guys doesn't fix it for so long time)

suppose you have two set of entities, People and Country, like this

public class People
{
public int CountryID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}

public class Country
{
public int Id { get; set; }
public string Name { get; set; }
}

and we has two set of collections which will be used to bind with the RadGridView and ComboBox column in the GridView

private ObservableCollection<People> peoples = new ObservableCollection<People>();
public ObservableCollection<People> Peoples
{
get { return peoples; }
set { peoples = value; }
}

private ObservableCollection<Country> countries = new ObservableCollection<Country>();
public ObservableCollection<Country> Countries
{
get { return countries; }
set { countries = value; }
}

than we assign some value to the two collections


foreach(var x in
new People[] {
new People { CountryID = 0, FirstName = "Sebastain", LastName = "Vettel" },
new People { CountryID = 1, FirstName = "Fernando", LastName = "Alonso" },
new People { CountryID = 2, FirstName = "James", LastName = "Button" }
})
{
Peoples.Add(x);
}


foreach(var x in
new Country[] {
new Country { Id = 0, Name = "Germany" },
new Country { Id = 1, Name = "Spain" },
new Country { Id = 2, Name = "UK" }
})
{
Countries.Add(x);
}

now the Peoples and Countris are ready to be binded to the XAML objects. Bind the DataContext

this.DataContext = this;

let's see the View XAML codes, the RadGridView like this:

<controls:ChildWindow

<telerik:RadGridView x:Name="radGridView"
AutoGenerateColumns="False" ItemsSource="{Binding Peoples}">
<telerik:RadGridView.Columns>
<telerik:GridViewComboBoxColumn
DataMemberBinding="{Binding CountryID}"
UniqueName="Country"
SelectedValueMemberPath="Id"
DisplayMemberPath="Name"
ItemsSource="{Binding Countries}"/>
<telerik:GridViewDataColumn DataMemberBinding="{Binding FirstName}" UniqueName="First Name"/>
<telerik:GridViewDataColumn DataMemberBinding="{Binding LastName}" UniqueName="Last Name"/>
</telerik:RadGridView.Columns>
</telerik:RadGridView>


Simple and straightforward, and let see the result, like this:









everything is fine. Now let's click the FirstName column, what you will see is like this:







the ComboBox column's content is empty, what's wrong? Is there anything coding problem?

The answer is nothing wrong, this is one of the Telerik Silverlight GridView's  famous bug.

What you have to do is to remove the ItemsSource binding in the XAML side and move the binding in the code-behind, this is ugly, meaning if you have to use MVVM you have to pass some parameters to the ViewMode(at lest the ComboBox object) and breaking the graceful of MVVM.

Let's do some change to meet Telerik's behaviour, remove the ComboBox Binding
<telerik:GridViewComboBoxColumn
DataMemberBinding="{Binding CountryID}"
UniqueName="Country"
SelectedValueMemberPath="Id"
DisplayMemberPath="Name"
ItemsSource="{Binding Countries}"/>
and add this to the code-behind:
((GridViewComboBoxColumn)this.radGridView.Columns["Country"]).ItemsSource = Countries;

Now run the application, everything is as expected.


3 comments:

  1. Resolved without static resource, but with cellTemplate.
    This template is used only for view data, while on edit is used the combo box.

    ReplyDelete
  2. Could you use the ItemSourceBinding property?

    ReplyDelete