Search code examples
wpfbindingdatacontexttextblock

Binding in listbox with textblocks not working


I have the following xaml code:

<ListBox Foreground="{Binding MyColor, Converter={local:ColorConverter}}" ItemsSource="{Binding LogCollection, Mode=TwoWay}" Grid.Row="1">
</ListBox>

This changes the foreground color for the entire listbox, so I modified the code in this way:

<ListBox ItemsSource="{Binding LogCollection, Mode=TwoWay}" Grid.Row="1">
   <ListBox.ItemTemplate>
      <DataTemplate>
      <TextBlock Foreground="{Binding MyColor, Converter={local:ColorConverter}}"  Text="{Binding}"/>
      </DataTemplate>
   </ListBox.ItemTemplate>
</ListBox>

In this way I wanted to set the foreground for an item instead for the entire listbox, but it is not working. How do I find the right datacontext ? MyColor is a property on my MainViewModel.

LATER EDIT WITH THE SOLUTION

Jens's answer was the one that showed me where I was wrong. Instead of storing simple message log strings in the ObservableCollection, I created a new class (LogItems) which contains a Message and a Color members. Now the LogCollection is typeof LogItems instead of strings.

I populate the listbox with the following code in my viewmodel:

LogItems logitem = new LogItems(myMessage, myColor);
LogCollection.Insert(0, logitem);

And the view has the following form. Also it doesn't require anymore to use RelativeSource, because the datacontext is the same.

<ListBox ItemsSource="{Binding LogCollection, Mode=TwoWay}" Grid.Row="1">                        
 <ListBox.ItemTemplate>                             
  <DataTemplate>
   <TextBlock Foreground="{Binding Path=Color, Converter={local:ColorConverter}}" Text="{Binding Path=Message}"/>
  </DataTemplate>
 </ListBox.ItemTemplate>
</ListBox>              

Thank you all for your answers which lead me to this solution.


Solution

  • The DataContext of generated container in a listbox is automatically set to the corresponding item, therefore your Binding does not find the Property MyColor. You need to use a RelativeSource binding to bind to the DataContext of the containing list:

    <TextBlock Foreground="{Binding DataContext.MyColor, 
                                    RelativeSource={RelativeSource 
                                            Mode=FindAncestor, 
                                            AncestorType={x:Type ListBox}}, 
                                    Converter={local:ColorConverter}}"  
               Text="{Binding}"/>