Jose
Jose

Reputation: 11091

WPF Combobox DisplayMemberPath

Ok, I looked at other questions and didn't seem to get my answer so hopefully someone here can.

Very simple question why does the DisplayMemberPath property not bind to the item?

<ComboBox Grid.Row="1" Grid.Column="2" ItemsSource="{Binding PromptList}" DisplayMemberPath="{Binding Name}" SelectedItem="{Binding Prompt}"/>

The trace output shows that it is trying to bind to the class holding the IEnumerable not the actual item in the IEnumerable. I'm confused as to a simple way to fill a combobox without adding a bunch a lines in xaml.

It simply calls the ToString() for the object in itemssource. I have a work around which is this:

<ComboBox Grid.Row="1" Grid.Column="2" ItemsSource="{Binding PromptList}"  SelectedItem="{Binding Prompt}">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

But in my opinion it's too much for such a simple task. Can I use a relativesource binding?

Upvotes: 70

Views: 113562

Answers (7)

joe blogs
joe blogs

Reputation: 142

from what i can figure,

"DisplayMemberPath" uses reflection to get the property name in the data context class, if it cant find it nothing will be displayed.

if class

class some_class{
  string xxx{ get; }
}

DisplayMemberPath=xxx, will show whatever value "xxx" is

if you want to concatenate properties from the datacontext you need to create an item template, which will show up in the header and the drop down list.

<ComboBox.ItemTemplate>
          <DataTemplate DataType="employee">
            <StackPanel Orientation="Horizontal">
              <TextBlock Text="{Binding first_name}" />
              <TextBlock Text="" />
              <TextBlock Text="{Binding last_name}" />
            </StackPanel>
          </DataTemplate>
        </ComboBox.ItemTemplate>

you cannot have "DisplayMemberPath" and "ComboBox.ItemTemplate" set at the same time.

Upvotes: 0

rmagnien
rmagnien

Reputation: 13

Trying this :

<ComboBox Grid.Row="1" Grid.Column="2" ItemsSource="{Binding PromptList}"  SelectedItem="{Binding Prompt}">
<ComboBox.ItemTemplate>
    <DataTemplate>
        <TextBlock Text="{Binding Content}"/>
    </DataTemplate>
</ComboBox.ItemTemplate>

Upvotes: 1

JJ_Coder4Hire
JJ_Coder4Hire

Reputation: 4891

Alternatively you don't need to set the DisplayMemberPath. you can just include an override ToString() in your object that is in your PromptList. like this:

class Prompt {
    public string Name = "";
    public string Value = "";

    public override string ToString() {
        return Name;
    }
}

The ToString() will automatically be called and display the Name parameter from your class. this works for ComboBoxes, ListBoxes, etc.

Upvotes: 3

Emu
Emu

Reputation: 71

You should change the MemberPath="{Binding Name}" to MemberPath="Name". Then it will work.

Upvotes: 7

Muad&#39;Dib
Muad&#39;Dib

Reputation: 29216

You are not binding to the data in the class, you are telling it to get it's data from the class member that is named by the member "name" so, if your instance has item.Name == "steve" it is trying to get the data from item.steve.

For this to work, you should remove the binding from the MemberPath. Change it to MemberPath = "Name" this tells it to get the data from the member "Name". That way it will call item.Name, not item.steve.

Upvotes: 10

paparazzo
paparazzo

Reputation: 45096

You could remove DisplayMemberPath and then set the path in the TextBlock.
The DisplayMemberPath is really for when you have no ItemTemplate.
Or you could remove your ItemTemplate and use DisplayMemberPath - in which case it basically creates a TextBlock for you. Not recomended you do both.

   <TextBlock text="{Binding Path=Name, Mode=OneWay}" 

Upvotes: 5

Ben M
Ben M

Reputation: 22492

DisplayMemberPath specifies the path to the display string property for each item. In your case, you'd set it to "Name", not "{Binding Name}".

Upvotes: 164

Related Questions