views:

178

answers:

5

I am trying to bind a combo box to a list of objects, and it works great, besides the selected value, am I missing somethign?

<ComboBox ItemsSource="{Binding OrderInfoVm.AllCountries}"
          SelectedValuePath="country_code" DisplayMemberPath="country_name" 
          SelectedValue="{Binding OrderInfoVm.BillingCountry}" />

Basically I want to bind value to country codes and set the selected value to the country code bound to OrderInfoVm.BillingCountry (which implements INotifyPropertyChanged)

Initially when the control loads selected value is empty, but on click BillingCountry is populated. Selected value does not seem to change. How can I remedy that?

A: 

Try changing it to SelectedItem and set Mode=TwoWay...

<ComboBox ItemsSource="{Binding OrderInfoVm.AllCountries}"
          SelectedValuePath="country_code" DisplayMemberPath="country_name" 
          SelectedItem="{Binding OrderInfoVm.BillingCountry, Mode=TwoWay}" />

Edit: You may not need to change it to SelectedItem, perhaps just setting TwoWay will work, but that is how I've done it in my own code.

Fara
For some reason neither worked. Also if I change the selectedvalue to be "US", it still doesn't work :( I don't get it
Greg R
SelectedItem won't work with SelectedValuePath because it selects the object itself.But if value is needed SelectedValue should be used.
Oleg
A: 

Please ensure that you've specified correct binding path. Try starting project in debug mode and look at the output window to see if there are any binding errors

Oleg
All binding paths are correct :(
Greg R
A: 

Give this a shot; I believe you have your SelectedValuePath and SelectedValue mixed up:

<ComboBox ItemsSource="{Binding OrderInfoVm.AllCountries}"
   SelectedValue="country_code" 
   DisplayMemberPath="country_name" 
   SelectedValuePath="{Binding OrderInfoVm.BillingCountry}" />

For Reference:

ItemsSource = Gets or sets a collection used to generate the content of the ItemsControl (ComboBox).

SelectedValue = Gets or sets the value of the SelectedItem, obtained by using SelectedValuePath.

SelectedValuePath = Gets or sets a value that indicates the path used to get the SelectedValue from the SelectedItem.

DisplayMemberPath = Gets or sets a path to a value on the source object to serve as the visual representation of the object.

Metro Smurf
No actually this is not correct in my case, selectedvaluepath and selectedvalue should be swapped, I tested it both ways
Greg R
A: 

I do agree with Alex that using SelectedItem gives the desired behaviour. See the code below. It works and will hopefully help you further:

    <Window x:Class="SelectedValueSpike.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <ComboBox ItemsSource="{Binding OrderInfoVm.AllCountries}" 
          SelectedValuePath="country_code" DisplayMemberPath="country_name"  
          SelectedItem="{Binding OrderInfoVm.BillingCountry}"
          IsSynchronizedWithCurrentItem="True"
          Name="AllCountriesBox"/>
        <TextBox Text="{Binding ElementName=AllCountriesBox, Path=SelectedValue}"/>
        <Button>
            Change the textbox to "Ca","NL",or "US" and click!
        </Button>
    </StackPanel>
</Window>

    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows;

    namespace SelectedValueSpike
    {
        public partial class Window1 : Window
        {
            public OrderInfoVm OrderInfoVm{ get; set;}
            public Window1()
            {
                InitializeComponent();
                OrderInfoVm=new OrderInfoVm();
                OrderInfoVm.AllCountries.Add(new Country("US","US of A"));
                OrderInfoVm.AllCountries.Add(new Country("NL","Netherlands"));
                OrderInfoVm.AllCountries.Add(new Country("Ca","Canada"));
                OrderInfoVm.BillingCountry = OrderInfoVm.AllCountries[1];
                DataContext = this;
            }
        }



public class OrderInfoVm:INotifyPropertyChanged
    {
        public OrderInfoVm()
        {
            AllCountries=new ObservableCollection<Country>();
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private ObservableCollection<Country> _allCountries;
        public ObservableCollection<Country> AllCountries
        {
            get { return _allCountries; }
            set
            {
                _allCountries = value;
                OnPropertyChanged("AllCountries");
            }
        }

        private Country _billingCountry;
        public Country BillingCountry
        {
            get { return _billingCountry; }
            set
            {
                _billingCountry = value;
                OnPropertyChanged("BillingCountry");
            }
        }

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

    public class Country
    {
        public string country_code { get; set; }
        public string country_name { get; set; }

        public Country(string code, string name)
        {
            country_code = code;
            country_name = name;
        }
    }
}
Dabblernl
Thanks a lot, so here is what happened, I was binding to a custom class that I was populating from the database. No matter what I tried it wouldn't select. After I copied the contents to a dictionary everything began working. I'm not really sure why is this like that. I think it's because the selected value was a string, and the object's value was of type SqlString. Could that be it?
Greg R
That is very much possible. You should have had a Databinding error though. You know about how to get a detailed debugging report in yout Output window? http://bea.stollnitz.com/blog/?p=52
Dabblernl
+1  A: 

Maybe you are trying to implement something similar to this: Bound ComboBox

Mihir Gokani
Thanks, not exactly, mine just binds to the database object, but this kinda helped :)
Greg R