Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

ComboBox Multibinding with ObjectDataProvider

Posted on 2010-08-26
8
Medium Priority
?
2,057 Views
Last Modified: 2013-11-12
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
Comment
Question by:Phil_Larby
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 4
8 Comments
 
LVL 29

Expert Comment

by:Gautham Janardhan
ID: 33652932
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
 
LVL 29

Expert Comment

by:Gautham Janardhan
ID: 33652934
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
 
LVL 29

Expert Comment

by:Gautham Janardhan
ID: 33652938
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
Get your Disaster Recovery as a Service basics

Disaster Recovery as a Service is one go-to solution that revolutionizes DR planning. Implementing DRaaS could be an efficient process, easily accessible to non-DR experts. Learn about monitoring, testing, executing failovers and failbacks to ensure a "healthy" DR environment.

 

Author Comment

by:Phil_Larby
ID: 33655930
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
 

Author Comment

by:Phil_Larby
ID: 33655933

<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
 

Author Comment

by:Phil_Larby
ID: 33655934

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

Accepted Solution

by:
Gautham Janardhan earned 2000 total points
ID: 33656114
i guess we need to add this line after LoadNewDataItem() in the ctr


            ((ObjectDataProvider)grdDetails.Resources["Counties"]).MethodParameters[0] = ((TestData)grdDetails.DataContext).CountryID;
0
 

Author Comment

by:Phil_Larby
ID: 33659908
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

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article describes a technique for converting RTF (Rich Text Format) data to HTML and provides C++ source that does it all in just a few lines of code. Although RTF is coming to be considered a "legacy" format, it is still in common use... po…
For most people, the WrapPanel seems like a magic when they switch from WinForms to WPF. Most of us will think that the code that is used to write a control like that would be difficult. However, most of the work is done by the WPF engine, and the W…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
In response to a need for security and privacy, and to continue fostering an environment members can turn to for support, solutions, and education, Experts Exchange has created anonymous question capabilities. This new feature is available to our Pr…

704 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question