3

I know that there are many questions regarding DataBinding a combobox and also there are many tutorials but I feel those tutorials hard. So, I am asking this question.

Suppose I have two tables in my database:

Customer

CustomerID
Name
GenderID

GenderTypes

GenderTypeID
GenderType

I have created my models using ADO.Net Entity Data Model. So, I am using Entity Framework.

Now I have a ViewModel in which I declare a property called Customers as below:

private List<Customer> _customers;
public List<Customer> Customers
{
    get
    {
        return _customers;
    }
    set
    {
        _customers = value;
        OnPropertyChanged("Customers");
    }
}

Now I have a View Like this:

<Window ......>

    <Window.DataContext>
        <vm:MainWindowViewModel />
    </Window.DataContext>

    <Grid>
        <Grid.RowDefinitions>
            ..
            ..
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            ..
            ..
        </Grid.ColumnDefinitions>

        <TextBlock Text="Name" ....../>
        <TextBox Text="{Binding Name}"...../>

        <TextBlock Text="Gender" ....../>
        <TextBox ItemsSource="????"
                 SelectedValue="????"
                 SelectedValuePath="????"...../>

    </Grid>
</Window>

I dont know how to bind the combobox, so that I can see Male and Female as the items of combobox and when I select I should get corresponding GenderID instead of GenderType.

I know this is a very simple and straight forward question but I am very much new to WPF and trying to learn it.

Khushi
  • 1,031
  • 4
  • 24
  • 48

2 Answers2

5

Try this:

<ComboBox 
    <!--ItemsSource bound to property of type collection of GenderTypes, containing all gender types you have -->
    ItemsSource="{Binding MyGenderTypes}" 
    <!--Tell comboBox to display GenderType property of selected GenderTypes-->
    DisplayMemberPath="GenderType" 
    <!--Tell comboBox that the SelectedValue should be GenderID property of selected GenderTypes-->
    SelectedValuePath="GenderID" 
    <!--SelectedValue bound to property of type int (the same type of GenderID)-->
    SelectedValue="{Binding SelectedGenderID, Mode=TwoWay}" />

You will get the combobox displaying GenderType, but the selected value will be the corresponding GenderID. Just as you wish...

Khushi
  • 1,031
  • 4
  • 24
  • 48
har07
  • 88,338
  • 12
  • 84
  • 137
  • I have tried to implement your xaml but I don't get anything in combobox. – Khushi Dec 11 '13 at 09:15
  • the code expect MyGenderTypes to be List or ObservableCollection, and it should be populated first so you can see them displayed in the combobox. Have you done that? – har07 Dec 11 '13 at 10:26
  • I tested the code, and the combobox displaying Male & Female as expected. I populated MyGenderTypes with 2 GenderTypes, the one with GenderType = "Male" GenderTypeID=0, and the othe with GenderType="Female" GenderTypeID=1 – har07 Dec 11 '13 at 10:48
3

Add Genders in ViewModel class

public List<GenderTypes> Genders
        {
            get
            {
                return _genders;
            }
            set
            {
                _genders = value;
                OnPropertyChanged("Genders");
            }
        }

After use like this.

<ListBox ItemsSource="{Binding Customers}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <TextBlock Text="Name" />
                        <TextBox Text="{Binding Name}" />
                        <TextBlock Text="Gender" />
                        <ComboBox ItemsSource="{Binding Genders,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}" DisplayMemberPath="GenderType" SelectedValue="{Binding GenderID}" SelectedValuePath="GenderTypeID"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
ebattulga
  • 10,774
  • 20
  • 78
  • 116
  • I think `DisplayMemberPath` need to be the name of the property and not a binding unless you plan to provide the name of the property dynamically. – Mat J Dec 11 '13 at 05:08
  • 1
    Just some suggestions. Instead of a `List` the better approach would be to use an `ObservableCollection`. – Sandesh Dec 11 '13 at 05:09
  • I have tried to apply your solution. But I don't get anything in the combobox items. So I checked Output window to find binding errors and there I got this error : `The ObjectContext instance has been disposed and can no longer be used for operations that require a connection`. – Khushi Dec 11 '13 at 08:50
  • When assign your `Entity Objects` to `Itemssource`, use `ToList()`. For Example `listBox.ItemsSource=db.Customers.ToList()` etc – ebattulga Dec 11 '13 at 08:55
  • But I don't want to use listbox as you did in the above example. I just want to have my combobox in Grid. But Grid doesn't have any ItemsSource Property. – Khushi Dec 11 '13 at 09:04
  • After deleting RelativeSource from ItemsSource I dont get any binding related error in output window but I dont get any Items in my Combobox. – Khushi Dec 11 '13 at 09:14
  • Yes. Grid don't have ItemsSource. I think you want display `Customers` with Gender Combobox. This is Correct? – ebattulga Dec 11 '13 at 09:34
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/42935/discussion-between-khushi-and-ebattulga) – Khushi Dec 11 '13 at 09:37
  • Thank you and 1 small question. How can I retrieve the value that user has selected? – Khushi Dec 12 '13 at 04:28
  • User selected value automatically updated to `Patient.Sex` property (). If you want to handle this `Patient` object. First rename Grid to `MyGrid`. After create new Instance of Patient from code behind like this `var CurrentPatient=new Patient(); MyGrid.DataContext=CurrentPatient;` After user selected, you simply use `CurrentPatient.Sex` – ebattulga Dec 12 '13 at 04:42
  • I have to work for approx. 2 hours to completely get that combobox to work as you suggested. But in the end all is well. Thank you once again to help me. – Khushi Dec 12 '13 at 07:52