tags:

views:

1424

answers:

4

I have a listbox where I bind the ItemsSource to a collection stored in the set DataContext object. This makes the list displayed using the ToString() function.

<ListBox ItemsSource="{Binding SomeCollection}"></ListBox>

Now I want to display a property for the objects in the collection instead. So I want to define a template etc to do this on all the objects in the bound list. I tried a variety of different approaches without success. I'd like to do something like this:

<ListBox ItemsSource="{Binding SomeCollection}">
    <ListBox.Template>
        <ControlTemplate>                                
            <ListViewItem Content="{Binding ThePropertyOnElm}"></ListViewItem>
        </ControlTemplate>
    </ListBox.Template>
</ListBox>

Can anyone help me make this right?

+2  A: 

Use the Path binding property:

<ListBox ItemsSource="{Binding SomeCollection}">
    <ListBox.Template>
        <ControlTemplate>                                
            <ListViewItem Content="{Binding Path=ThePropertyOnElm}"></ListViewItem>
        </ControlTemplate>
    </ListBox.Template>
</ListBox>

Note: The reason for the somewhat confusing name (Path) is that it can be extended to sub-properties etc. So if the ThePropertyOnElm property returns an object with a property called Name, you could write {Binding Path=ThePropertyOnElm.Name} etc.

Tor Haugen
No, that doesn't help. Anyway; I thought Path was optional on simple bindings like these where the only thing you specify is the path. Hence - your example equals mine. No?
stiank81
@Tor I don't believe this is any different to what was asked in the question. The `Path` attribute of `Binding` is the default content property, meaning that you don't have to include it explicitly as you've suggested. I don't think the original question is very clear about what is required though.
Drew Noakes
Hm yes, you're both right. I stand corrected.
Tor Haugen
+1  A: 

Here's a sample I recently posted on Code Project:

    <Window
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2006" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
      x:Class="GameSampleApp.Window1"
      x:Name="Window"
      Title="Sample App"
      Width="380" Height="240">
      <Window.Resources>
        <Style TargetType="ListBox">
          <Setter Property="Control.FontFamily" Value="Tahoma" />
          <Setter Property="Control.FontSize" Value="10" />
        </Style>
        <Style x:Key="FontStyle">
          <Setter Property="Control.FontFamily" Value="Verdana" />
          <Setter Property="Control.FontStyle" Value="Italic" />
          <Setter Property="Control.FontSize" Value="12"/>
        </Style>
        <DataTemplate x:Key="GamePersonTemplate">
          <Grid>
            <Grid.RowDefinitions>
              <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
              <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <TextBlock Width="40" Grid.Column="0" Text="{Binding Name, Mode=OneWay}" />
          </Grid>
        </DataTemplate>
      </Window.Resources>
      <Grid x:Name="LayoutRoot">
      <ListBox Padding="3" HorizontalAlignment="Left" Width="Auto" 
          ItemTemplate="{DynamicResource GamePersonTemplate}" 
          ItemsSource="{Binding}" VerticalAlignment="Top" Height="Auto"/>
      </Grid>
  </Window>

In this sample, I set the ItemsSource to point to the datacontext binding, which could be anywhere up the visual tree. The item template is defined in the Window.Resources, but could just as well be defined in a separate ResourceDictionary. Basically, this items template is going to show a single textblock for each item row, but it could be made to be much more complicated if necessary; that's the beauty of WPF.

Pete OHanlon
+9  A: 

you don't need to specify a template, you can just use the DisplayMemberPath property, like so:

<ListBox ItemsSource="{Binding SomeCollection}" DisplayMemberPath="ThePropertyOnElm" />

hope this helps!

Roel
That did the trick! Thanks :-)
stiank81
yeah, that's much simpler than my answer :) +1
Mark Synowiec
+3  A: 

I think this is what youre wanting to do:

<ListBox ItemsSource="{Binding SomeCollection}">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="{x:Type local:YourDataType}">                                
            <TextBlock Text="{Binding ThePropertyOnElm}" />
        </ControlTemplate>
    </ListBox.ItemTemplate>
</ListBox>

The Template for the ListBox is going to modify how the actual listbox looks, and itemtemplate is going to control how the individual items in the listbox will look. I changed the controltemplate into a DataTemplate and assigned it to the type of YourDataType. Also, I used a textblock within the data template instead of listboxitem since the datatemplate is being assigned to the listboxitem (which should contain some type of content instead of another listboxitem).

i havent tried compiling this so it might not be exactly correct. if it doesnt let me know and ill take the extra steps!

Mark Synowiec
Roel hit the mark, but use this if you end up needing to make it more complicated like displaying more than one property in the template.
Mark Synowiec
This looks like what I wanted - until Roel gave the simpler one, yes. Keeping this for later reference if I need to do something more complex. Thx!
stiank81