• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2085
  • Last Modified:

ComboBox Multibinding with ObjectDataProvider

I have 2 cmobo boxes - one a list of countries, and another a list of counties in that country. Both ItemsSources are bound to ObjectDataProviders and a multibinding on the country combo box SelectedValue sets a MethodParameter for the counties itemssource to filter the counties list.

This works fine when manually selecting a country in the combo, but when initially populating through binding the 0 value specified in the MethodParmeters (I am just using this as a default value for when no country is selected) is passed and no counties are returned.  The correct value is selected in the country combo box on load and the multibinding is working, but it seems the counties ObjectDataProvider is not updating when a new MethodParameter is specified.

Any ideas how to fix this?

 
<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>

<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>

Open in new window

0
Phil_Larby
Asked:
Phil_Larby
  • 4
  • 4
1 Solution
 
Gautham JanardhanCommented:
Cant tell why it's not working for you without the rest of the code.. Any way take a look at the code posted here (basically your code here + i filled in the rest of the stuff). This is working as per your requirement
0
 
Gautham JanardhanCommented:
converters , HCRCountry and HCRCounty
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:
xaml
<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
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
Phil_LarbyAuthor Commented:
Thanks for taking a look at this, however I dont think this resolves the isse.  I had the dependent combo boxes working fine when manully selecting a country from the country combo.  

The problem I have is when the form is bound to a business object containing a countryID.  When teh data context is set, the correct country is selected in the country combo, but the ItemsSource of the counties combo never updates.


public class TestData: INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public TestData()
        {
            CountryID = new Random().Next(1, 4);
            CountyID = 4;
        }

        int _countryID;
        public int CountryID
        {
            get { return _countryID; }
            set { _countryID = value; OnPropertyChanged("CountryID"); }
        }

        int _countyID;
        public int CountyID
        {
            get { return _countyID; }
            set { _countyID = value; OnPropertyChanged("CountyID"); }
        }

        public string ItemName
        {
            get {return "Item " + CountryID;}
            set { ;}
        }

        private void OnPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
    }

    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)
        {
            return values[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
 
Phil_LarbyAuthor Commented:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:common="clr-namespace:WpfApplication1"
        xmlns:system="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow" Height="350" Width="525">
    <Grid Name="grdDetails">
        <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>
            <TextBox Name="txtItem" 
                     Text="{Binding Path=ItemName}" />
            <ComboBox Name="cboCountry"
                  ItemsSource="{Binding Source={StaticResource Countries}}"
                  DisplayMemberPath="CountryName"
                  SelectedValuePath="CountryID">
                <ComboBox.SelectedValue>
                    <MultiBinding Converter="{StaticResource MultiConv}"  >
                        <Binding Path="CountryID" 
                                 UpdateSourceTrigger="PropertyChanged" />
                        <Binding Source="{StaticResource Counties}"    
                                 Path="MethodParameters[0]"    
                                 BindsDirectlyToSource="True"
                                 Mode="OneWayToSource"/>
                    </MultiBinding>
                </ComboBox.SelectedValue>
            </ComboBox>

            <ComboBox Name="cboCounty"
                  ItemsSource="{Binding Source={StaticResource Counties}}"
                  DisplayMemberPath="CountyName"
                  SelectedValuePath="CountyID">
            </ComboBox>
            
            <Button Name="btnNewItem" 
                    Content="New Item" 
                    Width="100" 
                    Margin="10" Click="btnNewItem_Click" />
        </StackPanel>

    </Grid>
</Window>

Open in new window

0
 
Phil_LarbyAuthor Commented:

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            LoadNewDataItem();
        }

        private void btnNewItem_Click(object sender, RoutedEventArgs e)
        {
            LoadNewDataItem();
        }

        private void LoadNewDataItem()
        {
            grdDetails.DataContext = new TestData();
        }
    }
}

Open in new window

0
 
Gautham JanardhanCommented:
i guess we need to add this line after LoadNewDataItem() in the ctr


            ((ObjectDataProvider)grdDetails.Resources["Counties"]).MethodParameters[0] = ((TestData)grdDetails.DataContext).CountryID;
0
 
Phil_LarbyAuthor Commented:
Forcing the update in code like this does work, however it is not the clean solution I was hoping for.  I will continue to investigate reasons why the binding may not work - but will hapillly award you you the points if can't find a better solutions.
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 4
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now