GridViewComboBoxColumn ItemsSource binding issue

4 posts, 0 answers
  1. Tim
    Tim avatar
    3 posts
    Member since:
    Feb 2016

    Posted 13 May Link to this post

    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.

  2. Tim
    Tim avatar
    3 posts
    Member since:
    Feb 2016

    Posted 13 May Link to this post

    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"); }
            }
     
        }

  3. UI for WPF is Visual Studio 2017 Ready
  4. Stefan X1
    Admin
    Stefan X1 avatar
    520 posts

    Posted 17 May Link to this post

    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.
  5. Tim
    Tim avatar
    3 posts
    Member since:
    Feb 2016

    Posted 17 May in reply to Stefan X1 Link to this post

    That's exactly what I needed. I missed that property when I browsed through that topic the first time. Thanks!
Back to Top