Change the Foreground of certain items in a Listbox, via Style, using a Converter?

Asked

Viewed 368 times

1

I have a ListBox where the data source is a ObservableCollection<string>.

I would like the items that start with "ATTENTION" to have the red source.

I could do it using one DataTemplate, one Converter and a model to apply in a Label or TextBlock.

But since I don’t have DataTemplate changed the scenario. Could I add the Binding and Convert in a Setter style?

<ListBox x:Name="lstLog" Height="160" Width="775">
         <ListBox.ItemContainerStyle>
             <Style TargetType="ListBoxItem">
                  <Setter Property="Height" Value="19" />
             </Style>
          </ListBox.ItemContainerStyle>
 </ListBox>

The convert I know would be something like this:

public class CorLogConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value.ToString().StartsWith("ATENÇÃO"))
             return new SolidColorBrush(Colors.Red);
        else
             return new SolidColorBrush(Colors.Black);
    }     
}
  • Post the entire statement of Listbox.

  • @ramaral I’ve already put the Listbox shampoo. I don’t understand what you mean by "statement" in this context

  • Since I didn’t see any Binding with Observablecollection I thought it was not complete. So you’re doing it in code Behind. Is it possible to put it? Is that having a complete example is easier to work on an answer.

2 answers

2

EDIT

The solution is to get a way to get the Path representing the item being rendered.

Contrary to what I said this is possible.

Simply do not indicate any Path on the tag <Binding> or use <Binding Path=".">, the point represents the path of "source current"

<ListBox x:Name="lstLog" Height="160" Width="775">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Height" Value="19" />

            <Setter Property="Foreground">
                <Setter.Value>
                    <Binding>
                        <Binding.Converter>
                            <testeWpf:CorLogConverter/>
                        </Binding.Converter>
                    </Binding>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

-----------------------------------------------------------------------------

I may be wrong but it’s not possible.

To make the Binding it is necessary a Path and then get the Value. The problem lies there, there is no way to get the Path representing the item being rendered.

The only item that can be accessed is the selected item.

The following example changes the text color of all items when one is selected starting with ATTENTION:

<ListBox x:Name="lstLog" Height="160" Width="775" IsSynchronizedWithCurrentItem="True">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Height" Value="19" />

            <Setter Property="Foreground">
                <Setter.Value>
                    <Binding ElementName="lstLog" Path="Items/">
                        <Binding.Converter>
                            <testeWpf:CorLogConverter/>
                        </Binding.Converter>
                    </Binding>
                </Setter.Value>
            </Setter>

        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

Something identical can be obtained by using a Datatrigger:

<ListBox x:Name="lstLog" Height="160" Width="775" IsSynchronizedWithCurrentItem="True">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Height" Value="19" />

            <Style.Triggers>
                <DataTrigger Binding="{Binding ElementName=lstLog, Path=Items/}" Value="ATENÇÃO">
                    <Setter Property="Foreground" Value="Red" />
                </DataTrigger>
            </Style.Triggers>

        </Style>
    </ListBox.ItemContainerStyle>
</ListBox> 
  • Thanks for the reply, but only the selected would not attend. I posted my solution.

  • Yes, I know you wouldn’t answer, I put it just to illustrate how to use a convert in a style

0

I was able to solve by continuing using my ObservableCollection<string> without using a model, it was sufficient that in the Binding i left blank. I was used to using for example "Binding nomePropriedade, Converter = ....". But I had to use Datatemplate:

View

<ListBox x:Name="lstLog" Height="160" Width="775">
     <ListBox.ItemTemplate>
         <DataTemplate>
             <TextBlock Text="{Binding}" Foreground="{Binding Converter={StaticResource localConverterCorLog}}"  />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

View.Cs

this.arrLog = new ObservableCollection<string>();
lstLog.ItemsSource = this.arrLog;

Convert

Actually I needed red when I had "ATTENTION"

public class ConverterCorLog : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value != null && value.ToString().Contains("ATENÇÃO"))
            return new SolidColorBrush(Colors.Red);
        else
            return new SolidColorBrush(Colors.Black);

    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

App.xaml

<classes:ConverterCorLog x:Key="localConverterCorLog" />
  • Using a Datatemplate it’s easy, I didn’t suggest it because you said you didn’t want to use it.

  • True. I looked but on the net and saw that it was very complicated, then I let go. As I said, I didn’t know that I could leave the Binding tag in "white"

  • 1

    {Binding} is equivalent to {Binding Path=.}, the point indicates the "source current", in this case the contents of the list item.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.