tags:

views:

1107

answers:

4

I want to get my ComboBox in XAML to bind to my List collection of custom objects in code behind.

Currently the ComboBox lists for each entry "dpwpf.Contact" which is my {namespace}.{classname}.

What do I need to put in the XAML to tell it to list out, e.g. LastName + FirstName?

I know it's something like {Binding Path=... Value=...} but I can't get it.

XAML:

<Window x:Class="dpwpf.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>
        <StackPanel>
            <TextBlock Text="Select the contact:"/>
            <ComboBox Name="theContactList"/>
        </StackPanel>
    </StackPanel>
</Window>

Code Behind:

namespace dpwpf
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            StoreDB db = new StoreDB();
            List<Contact> contacts = db.GetContacts()
            theContactList.ItemsSource = contacts.ToList();
        }
    }
}

Answer:

<Window x:Class="dpwpf.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"
    xmlns:local="clr-namespace:dpwpf">

    <Window.Resources>
        <DataTemplate DataType="{x:Type local:Contact}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding LastName}"/>
                <TextBlock Text=" "/>
                <TextBlock Text="{Binding FirstName}"/>
            </StackPanel>
        </DataTemplate>
    </Window.Resources>

    <StackPanel>
        <StackPanel Margin="10">
            <TextBlock Text="Contact Name:" Foreground="#555"/>
            <TextBox Name="theName"/>
        </StackPanel>
        <StackPanel>
            <TextBlock Text="Select the contact:"/>
            <ComboBox Name="theContactList"/>
        </StackPanel>
    </StackPanel>
</Window>
+3  A: 

you need to use DisplayMember="TheValue"

you can add this in the XAML or in the CLR also note your binding in cose and not through the XAML. i think this relates to a prvious question of yours. which implements the binding through ObjectDataProvider use that example and add the DisplayMemeber="memeber" in the XAML

HTH, Eric,

yes, this will work, but I want to be able to format the text instead the combobox item, e.g. lastname + " " + firstname
Edward Tanguay
Hi Edward, sorry it took me so long.you have a couple of ways to tackle the problem.1) add a property FullName which returns this.lastname + ", " + this.firstname. and use it as the deisplay member.HH,Eric
2) use a IValueConverter to convert the displaed vaule, you can use as a static resource in the XAML and add the Converter XML propert.
+1  A: 

Hi Edward

What the binding mechanism is doing is calling ToString() on the type that is being bound. Because I guess you're not overriding ToString() it'll just so the namespace.type instead of something useful.

As rebelious says, you can use DisplayMember to tell the binding to use a property of that name for the display value or you can override ToString() as below to get your custom property to show.

public void Contact
{
 public string FirstName { get; set; }
 public override string ToString()
 {
   return FirstName; 
 }
}
Ray Booysen
this is nice, but I might have other controls which want to override differently, and as far as I understand I only get one override.
Edward Tanguay
+3  A: 

You can override the ToString method of Contact, or you can define a DataTemplate in WPF.

xmlns:dpwpf="... namespace of dpwpf"

<Window.Resources>
    <DataTemplate DataType="{x:Type dpwpf:Contact}">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding LastName}">
            <TextBlock Text=" ">
            <TextBlock Text="{Binding FirstName}">
        </StackPanel>
    </DataTemplate>
</Window.Resources>

This allows you to define how a Contact object will appear anywhere in the window. If you want to limit this to the ComboBox you can add the DataTemplate just to the ComboBox resources.

See also What does "{Binding}" mean? by Bea Stollnitz

Cameron MacFarland
wow, I'm going to have to let that sink in, you have a StackPanel going on inside a ComboBoxItem. So the posted answer code works above but I don't see the connection between the my ComboBox and the DataTemplate, I'm expecting the DataTemplate to have a name and the ComboBox refer to it.
Edward Tanguay
The combobox shows Contact objects. So WPF searches the visual tree for a DataTemplate that displays Contacts, and uses that template. If there's no template then it defaults to using ToString. There is no direct connection except through the Contact object.
Cameron MacFarland
This is the beauty of WPF. You define a way of showing a data object, and then wherever that object turns up the template is used to display it.
Cameron MacFarland
Also, the stackpanel was just there to get the "firstname" + "lastname" look. You could do the same thing with a Binding converter, but doing it this way is easier.
Cameron MacFarland
A: 

Just add this in you ComboBox tag (xaml code)

TextSearch.TextPath ="Title"

ToString() modification affects all future cases you need it, I don't recommend you to do that.

See that example: http://simplesample.site90.com/wpf_combobox.php

Rafa