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

GridViewComboBoxColumn ItemsSource binding issue

3 Answers 883 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Tim
Top achievements
Rank 1
Tim asked on 13 May 2016, 03:58 PM

I'm having an ItemsSource binding issue with a GridViewComboBoxColumn.

In my ViewModel I have a list of Location objects which consists of a Continent object and a list of Country objects for the specified Continent. In my UI I have a RadGridView with the ItemsSource bound to my list of locations.The RadGridView has 2 GridViewComboBoxColumns; one for Continent and one for Country. For the Continent column I have the DataMemberBinding set to bind to the Continent property of the Location object and the ItemsSource set to my list of Continent objects (defined in the ViewModel). This binding works as expected. For the Country column I have the DataMemberBinding set to bind to the Continent's SelectedCountry property and the ItemsSource set to bind to the Continent's Countries property (list of countries on that continent). When I run my program I get a binding error stating that it can't find the property Continent on object ViewModel which means it's not looking at the row data context for the property but rather the RadGridView's data context. I assume this is just a path issue on my side but I haven't been able to figure out how to bind to the correct path.

 

Just to make sure I wasn't trying something that wasn't possible I also set up a similar binding on two RadComboBox (using a Continent object property in the ViewModel) and also within the RadGridView's row details. Both have the correct binding and expected behavior so I could use the row details approach if need be.

 

Please see the attached project for an example.

3 Answers, 1 is accepted

Sort by
0
Tim
Top achievements
Rank 1
answered on 13 May 2016, 07:31 PM

It won't allow me to attach my project .zip file so here is the code.

MainWindow.xaml (nothing in the code behind)

<Window x:Class="WpfApplication1.MainWindow"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:ViewModel />
    </Window.DataContext>
    <DockPanel>
        <telerik:RadComboBox
            DockPanel.Dock="Top"
            SelectedItem="{Binding TestContinent}"
            ItemsSource="{Binding Continents}"/>
        <telerik:RadComboBox
            DockPanel.Dock="Top"
            SelectedItem="{Binding TestContinent.SelectedCountry}"
            ItemsSource="{Binding TestContinent.Countries}"/>
        <telerik:RadGridView
            x:Name="rgvStuff"
            AutoGenerateColumns="False"
            ItemsSource="{Binding Locations}"
            RowDetailsVisibilityMode="VisibleWhenSelected">
            <telerik:RadGridView.RowDetailsTemplate>
                <DataTemplate>
                    <StackPanel>
                        <telerik:RadComboBox
                            SelectedItem="{Binding Continent}"
                            ItemsSource="{x:Static local:ViewModel.Continents}"/>
                        <telerik:RadComboBox
                            SelectedItem="{Binding Continent.SelectedCountry}"
                            ItemsSource="{Binding Continent.Countries}"/>
                    </StackPanel>
                </DataTemplate>
            </telerik:RadGridView.RowDetailsTemplate>
            <telerik:RadGridView.Columns>
                <telerik:GridViewComboBoxColumn
                    Header="Continent"
                    DataMemberBinding="{Binding Continent}"
                    ItemsSource="{Binding Continents}"/>
                <telerik:GridViewComboBoxColumn
                    Header="Country"
                    ItemsSource="{Binding Continent.Countries}"
                    DataMemberBinding="{Binding Continent.SelectedCountry}">
                </telerik:GridViewComboBoxColumn>
            </telerik:RadGridView.Columns>
        </telerik:RadGridView>
    </DockPanel>
</Window>

Continent.cs

public class Continent : INotifyPropertyChanged
    {
        public Continent()
        {
            Countries = new ObservableCollection<Country>();
        }
 
        public string Code { get; set; }
 
        public string Name { get; set; }
 
        public ObservableCollection<Country> Countries { get; private set; }
 
        private Country m_country;
 
        public Country SelectedCountry
        {
            get { return m_country; }
            set { m_country = value; OnPropertyChanged("SelectedCountry"); }
        }
 
 
        public override string ToString()
        {
            return Name;
        }
 
        public event PropertyChangedEventHandler PropertyChanged;
 
        void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

Country.cs

public class Country : INotifyPropertyChanged
    {
        public int ID { get; set; }
 
        public string Name { get; set; }
 
        public string ContinentCode { get; set; }
 
        public event PropertyChangedEventHandler PropertyChanged;
 
        public override string ToString()
        {
            return Name;
        }
 
        void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

Location.cs

public class Location : INotifyPropertyChanged
    {
 
        private Continent m_continent;
 
        public Continent Continent
        {
            get { return m_continent; }
            set
            {
                m_continent = value;
                OnPropertyChanged("Continent");
            }
        }
 
        public ObservableCollection<Country> Countries
        {
            get
            {
                ObservableCollection<Country> retval = null;
 
                if (m_continent != null)
                {
                    retval = m_continent.Countries;
                }
 
                return retval;
            }
        }
 
 
        public event PropertyChangedEventHandler PropertyChanged;
 
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

ViewModel.cs

public class ViewModel : ViewModelBase
    {
        public ViewModel()
        {
            Locations = new ObservableCollection<Location>();
            Continents = new ObservableCollection<Continent>();
 
            Country uk = new Country() { ContinentCode = "EU", ID = 233, Name = "UK" };
            Country germany = new Country() { ContinentCode = "EU", ID = 82, Name = "Germany" };
            Country usa = new Country() { ContinentCode = "NA", ID = 234, Name = "US" };
 
            Continent europe = new Continent() { Code = "EU", Name = "Europe" };
            Continent northAmerica = new Continent() { Code = "NA", Name = "North America" };
 
            europe.Countries.Add(uk);
            northAmerica.Countries.Add(usa);
            europe.Countries.Add(germany);
 
            europe.SelectedCountry = germany;
 
            Continents.Add(europe);
            Continents.Add(northAmerica);
 
            Locations.Add(new Location() { Continent = europe});
            Locations.Add(new Location() { Continent = northAmerica });
 
            TestContinent = europe;
 
            Name = "test";
        }
 
        public ObservableCollection<Location> Locations { get; private set; }
 
        public static ObservableCollection<Continent> Continents { get; private set; }
 
        private Continent m_continent;
 
        public Continent TestContinent
        {
            get { return m_continent; }
            set { m_continent = value; OnPropertyChanged("TestContinent"); }
        }
 
 
        private string m_name;
 
        public string Name
        {
            get { return m_name; }
            set { m_name = value; OnPropertyChanged("Name"); }
        }
 
    }

0
Stefan
Telerik team
answered on 17 May 2016, 12:26 PM
Hello Tim,

Thanks for the code provided.

Can you please check out the ComboBox Column help topic, as it demonstrates how the  GridViewComboBox column can be configurated? Basically, in order to bind the second column's ItemsSource to a property of the bound data item, you can try using the ItemsSourceBinding property of GridViewComboBoxColumn.

Hope this helps.

All the best,
Stefan X1
Telerik
Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
0
Tim
Top achievements
Rank 1
answered on 17 May 2016, 03:26 PM
That's exactly what I needed. I missed that property when I browsed through that topic the first time. Thanks!
Tags
GridView
Asked by
Tim
Top achievements
Rank 1
Answers by
Tim
Top achievements
Rank 1
Stefan
Telerik team
Share this question
or