WPF DataGrid using 2 DataGridComboBoxColumns and reloading the second ComboBox when the first one changes.


Open in new window


Open in new window

Hi guys,  I would like to know how to link 2 data bound DataGridComboBox columns in WPF such that when the first combo box value changes the second one is reloaded based upon a filter or selection from the first combo box.  

I have the DataGrid and DataGridComboBoxColumn's pretty much working correctly except for this particular problem.

There is a master – detail relationship between Event Type and Competition such that when the Event Type changes the Competitions combo box needs to be reloaded.  Please see the table definitions below:

CREATE TABLE [dbo].[EventTypes](
      [EventTypeID] [int] IDENTITY(1,1) NOT NULL,
      [Name] [nvarchar](255) NOT NULL,
 CONSTRAINT [PK_EventTypeID] PRIMARY KEY CLUSTERED
(
      [EventTypeID] ASC
)
GO

CREATE TABLE [dbo].[Competitions](
      [CompetitionID] [int] IDENTITY(1,1) NOT NULL,
      [EventTypeID] [int] NOT NULL,
      [Name] [nvarchar](255) NOT NULL,
 CONSTRAINT [PK_CompetitionID] PRIMARY KEY CLUSTERED
(
      [CompetitionID] ASC
)

GO

ALTER TABLE [dbo].[Competitions]  WITH CHECK ADD  CONSTRAINT [FK_Competitions_EventTypes] FOREIGN KEY([EventTypeID])
REFERENCES [dbo].[EventTypes] ([EventTypeID])
GO

ALTER TABLE [dbo].[Competitions] CHECK CONSTRAINT [FK_Competitions_EventTypes]
GO


Find enclosed samples of my code (I have removed many irrelevant columns from the grid for clarity)… I am using .NET 4.0 with VS 2010 and C#.

// Extract from Main.xaml

<DataGrid x:Name="datagridBetsPlaced" DataContext="{StaticResource usp_BetsPlaced_SelectForUserAccountIDViewSource}" AutoGenerateColumns="False" EnableRowVirtualization="True"
HorizontalAlignment="Stretch" ItemsSource="{Binding}"
            RowDetailsVisibilityMode="VisibleWhenSelected" VerticalAlignment="Stretch"
            AlternatingRowBackground="Aqua" CanUserAddRows="False" Margin="0,1,0,-1">

    <DataGrid.Resources>
        <ObjectDataProvider x:Key="eventTypesDataProvider" ObjectType="{x:Type my:Database}" MethodName="GetEventTypes"/>
        <ObjectDataProvider x:Key="competitionsDataProvider" ObjectType="{x:Type my:Database}" MethodName="GetCompetitions"/>
    </DataGrid.Resources>

    <DataGrid.Columns>
        <DataGridTextColumn x:Name="betIDColumn" Binding="{Binding Path=BetID}" Header="Bet ID" IsReadOnly="True" Width="SizeToHeader" Visibility="Hidden" />
        <DataGridComboBoxColumn x:Name="eventTypeIDColumn" Width="150" Visibility="Visible"
            SelectedValueBinding="{Binding EventTypeID}"
            ItemsSource="{Binding Source={StaticResource eventTypesDataProvider}}"
            SelectedValuePath="ItemData"
            DisplayMemberPath="Text"
            Header="Event Type"
        />
        <DataGridComboBoxColumn x:Name="competitionIDColumn" Width="150" Visibility="Visible"
            SelectedValueBinding="{Binding CompetitionID}"
            ItemsSource="{Binding Source={StaticResource competitionsDataProvider}}"
            SelectedValuePath="ItemData"
            DisplayMemberPath="Text"
            Header="Competition"
        />
        <DataGridTextColumn x:Name="decimalOddsColumn" Binding="{Binding Path=DecimalOdds}" Header="Decimal Odds" Width="100" />
        <DataGridTextColumn x:Name="stakeColumn" Binding="{Binding Path=Stake}" Header="Stake" Width="75" />
        <DataGridTextColumn x:Name="actualReturnColumn" Binding="{Binding Path=ActualReturn}" Header="Actual Return" Width="100" />
    </DataGrid.Columns>
</DataGrid>


// Extract from Database class

public static class Database
{
  public static List<ListComboData> GetEventTypes()
  {
      return LoadEventTypesList(Database.LanguageID);
  }

  // I need to pass an EventTypeID parameter into here which is based upon the SelectedValue in the Event Type DataGridComboBoxColumn
  public static List<ListComboData> GetCompetitions(int EventTypeID)
  {
      return LoadCompetitionsListForEventTypeID(EventTypeID);
  }

        private static List<ListComboData> LoadEventTypesList()
        {

            List<ListComboData> ListData = new List<ListComboData>();

            try
            {
                SqlCommand thisCommand = Connection.CreateCommand();
                thisCommand.CommandType = CommandType.StoredProcedure;
                thisCommand.CommandText = "dbo.usp_EventTypes_SelectForList";

                SqlDataReader reader = thisCommand.ExecuteReader();

                while (reader.Read())
                {
                    ListData.Add(new ListComboData(reader["Name"].ToString(), (int)reader["EventTypeID"]));
                }

                reader.Close();

            }
            catch (SqlException e)
            {
                MessageBox.Show(e.Message);
            }

            return ListData;
        }

        private static List<ListComboData> LoadCompetitionsListForEventTypeID(int EventTypeID)
        {

            List<ListComboData> ListData = new List<ListComboData>();

            try
            {
                SqlCommand thisCommand = Connection.CreateCommand();
                thisCommand.CommandType = CommandType.StoredProcedure;
                thisCommand.CommandText = "dbo.usp_Competitions_SelectForListByEventTypeID";

                SqlParameter paramEventTypeID = thisCommand.Parameters.Add("@EventTypeID", SqlDbType.Int);
                paramEventTypeID.Direction = ParameterDirection.Input;

                paramLanguageID.Value = LanguageID;
                paramEventTypeID.Value = EventTypeID;

                SqlDataReader reader = thisCommand.ExecuteReader();

                while (reader.Read())
                {
                    ListData.Add(new ListComboData(reader["Name"].ToString(), (int)reader["CompetitionID"]));
                }

                reader.Close();
            }
            catch (SqlException e)
            {
                MessageBox.Show(e.Message);
            }

            return ListData;
        }

}


jboydellAsked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
Gautham JanardhanConnect With a Mentor Commented:
Converters, Country and Counties
public class HCRCountry
    {
        public string CountryName { get; set; }
        public int CountryID { get; set; }
        public List<HCRCountry> getCountryAll()
        {
            return new List<HCRCountry>()
            {
                new HCRCountry()
                {
                    CountryID = 1,
                    CountryName = "India1"
                },
                new HCRCountry()
                {
                    CountryID = 2,
                    CountryName = "India2"
                },
                new HCRCountry()
                {
                    CountryID = 3,
                    CountryName = "India3"
                },
                new HCRCountry()
                {
                    CountryID = 4,
                    CountryName = "India4"
                }
            };
        }
    }

    public class HCRCounty
    {
        public string CountyName { get; set; }
        public int CountyID { get; set; }
        public List<HCRCounty> getCountiesByCountry(int country)
        {
            return new List<HCRCounty>()
            {
                new HCRCounty()
                {
                    CountyName = "County for country" + country.ToString(),
                    CountyID = 1
                }
            };
        }

        public List<HCRCounty> getCountiesByCountry(object country)
        {
            return getCountiesByCountry((int)country);
        }
    }

    public class ConverterTemp : IMultiValueConverter, IValueConverter
    {
        #region IMultiValueConverter Members

        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (values != null && values.Length == 2 && (values[0] as HCRCountry) != null)
            {
                var temp = values[0] as HCRCountry;
                return temp.CountryID;
            }
            return 0;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            return new object[] { value, value };
        }

        #endregion

        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value;
        }

        #endregion
    }

Open in new window

0
 
Gautham JanardhanCommented:
a sample which implements this functionality. two combo's filled by country and counties. On change of country the counties of that country is populated in the county combo.
0
 
Gautham JanardhanCommented:
Xaml

also these lines in code behind

this.DataContext= this  -> put this in initialize component

and a property

public int CountryID { get; set; }
<Grid.Resources>
            <common:ConverterTemp x:Key="MultiConv" />
            <common:ConverterTemp x:Key="IDConv" />
            <ObjectDataProvider x:Key="Countries"
                            ObjectType="{x:Type common:HCRCountry}"
                            MethodName="getCountryAll" />
            <ObjectDataProvider x:Key="Counties"
                            ObjectType="{x:Type common:HCRCounty}"
                            MethodName="getCountiesByCountry">
                <ObjectDataProvider.MethodParameters>
                    <system:Int32>0</system:Int32>
                </ObjectDataProvider.MethodParameters>
            </ObjectDataProvider>
        </Grid.Resources>
        <StackPanel>
            <ComboBox Name="cboCountry"
                  Grid.Column="3"
                  Grid.Row="2"
                  Margin="5,2"
                  ItemsSource="{Binding Source={StaticResource Countries}}"
                  DisplayMemberPath="CountryName"
                  SelectedValuePath="CountryID">
                <ComboBox.SelectedValue>
                    <MultiBinding Converter="{StaticResource MultiConv}"  >
                        <Binding Path="CountryID" 
                                 Converter="{StaticResource IDConv}" 
                                 UpdateSourceTrigger="PropertyChanged" />
                        <Binding Source="{StaticResource Counties}"    
                                 Path="MethodParameters[0]"    
                                 BindsDirectlyToSource="True"
                                 Converter="{StaticResource IDConv}"
                                 Mode="OneWayToSource"/>
                    </MultiBinding>
                </ComboBox.SelectedValue>
            </ComboBox>
            
            <ComboBox Name="cboCounty"
                  ItemsSource="{Binding Source={StaticResource Counties}}"
                  DisplayMemberPath="CountyName"
                  SelectedValuePath="CountyID">
            </ComboBox>

        </StackPanel>

Open in new window

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.