I'm confused as to how bindings are resolved when I have both an ItemsSource
and an ItemTemplate
in a WPF ListBox
.
I have an ObservableCollection<int>
called ListOfIndexes
. For each index, I want to look up its record in a database table. I hope to do that in the IndexToObjectDescriptionConverter
.
<ListBox ItemsSource="{Binding ListOfIndexes}"
ItemTemplate="{Binding Converter={StaticResource IndexToObjectDescriptionConverter}}" />
But a breakpoint in the converter is telling me that the value being read in by the ItemTemplate
binding is of the window itself — i.e., the DataContext
of the ItemsSource
and ItemsTemplate
is the same.
Pardon a bit of candidness, but this seems DUMB. The entire point of the ItemTemplate
is to render each element within the ItemsSource
, so I guess I figured that the DataContext
of the ItemTemplate
would be the individual element being rendered.
So, that said, how do I tell the ItemTemplate
that it should worry about the individual elements represented by the ItemsSource
and not use the entire window's DataContext
?
You need to use a data template for the ItemTemplate. This is then applied to each item in the list
MSDN docs are here:
http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.itemtemplate(v=vs.110).aspx
The issue her is about data context scope. When you bind any property on the ListBox, it will use the data context of the ListBox - hence why that data context is being passed to the converter. If you set a data template inside the ItemTemplate, it will apply that template to each item in the list. I guess based on the simple code you've provided you would need to have the converter inside the data template:
<ListBox ItemsSource="{Binding ListOfIndexes}">
<ListBox.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding Converter={StaticResource IndexToObjectDescriptionConverter}}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In this case, the ContentControl will be rendered for each item, with that item as it's data context.
Firstly, I'd advise that you have a good read of the Data Templating Overview page in MSDN so that you can get a better understanding of this data binding process.
I want to look up its record in a database table. I hope to do that in the IndexToObjectDescriptionConverter.
That is your first mistake. An IValueConverter
is responsible for converting data bound values, not accessing databases. Access your data in your view model and populate public properties with the results. Then data bind those properties to UI controls in the XAML.
Pardon a bit of candidness, but this seems DUMB
Only to those that do not understand the situation.
how do I tell the ItemTemplate that it should worry about the individual elements represented by the ItemsSource and not use the entire window's DataContext?
You don't tell it anything... simply defining the correct XAML is enough:
In Resources
:
<DataTemplate x:Key="SomeDataTemplate">
<!-- The DataContext here is set to an item from the data bound collection -->
</DataTemplate>
In XAML:
<ListBox ItemsSource="{Binding ListOfIndexes}"
ItemTemplate="{StaticResource SomeDataTemplate}" />
That's it.