0

I am using VS2010 - WPF - C# and I am building a securities ticker that show some values to the user in a listview.

My listview looks like this:

<ListView Height="325" Margin="8,8,8,0" x:Name="listView1" VerticalAlignment="Top" BorderThickness="3" FontWeight="Bold" FontSize="12" Foreground="White" Background="{x:Null}" BorderBrush="{x:Null}" Style="{DynamicResource ListViewStyle1}">
  <ListView.View>
    <GridView>
      <GridViewColumn Header="name" DisplayMemberBinding="{Binding company_name}" Width="200" />
      <GridViewColumn Header="symbol" DisplayMemberBinding="{Binding symbol}" Width="50" />
      <GridViewColumn Header="price"  DisplayMemberBinding="{Binding price}" Width="75" />
      <GridViewColumn Header="percent " DisplayMemberBinding="{Binding change_percent}" Width="50" />
    </GridView>
  </ListView.View>
</ListView>

I would like some rows in my listview to be coloured in red, others in green, depending on the percent value at runtime, but I don't know how.

Best Regards

H.B.
  • 166,899
  • 29
  • 327
  • 400

2 Answers2

5

To do what you're looking for, H.B's answer is it.

However consider this from a usability standpoint. Some people are colour-blind and will find certain font/background colour combinations difficult or impossible to read. You might be better considering having a colour ellipse in a new first column, and keeping the standard background/foreground colours as per the users' selections in Windows. The approach to setting the background brush of the ellipse would be the same as H.B's answer for the font.

Even for people who aren't colour-blind, trying to read bright green text on a white background might be challenging (imagine those people sat with a window behind them, for example).

Just a thought.

Community
  • 1
  • 1
Neil Barnwell
  • 41,080
  • 29
  • 148
  • 220
3

Bind the Foreground of your control to the change_percent and use a ValueConverter to turn it into a Brush.

Here would be a basic converter which changes from red to yellow to green:

public class PercentToBrushConverter : IValueConverter
{
    //http://stackoverflow.com/questions/3722307/is-there-an-easy-way-to-blend-two-system-drawing-color-values/3722337#3722337
    private Color Blend(Color color, Color backColor, double amount)
    {
        byte r = (byte)((color.R * amount) + backColor.R * (1 - amount));
        byte g = (byte)((color.G * amount) + backColor.G * (1 - amount));
        byte b = (byte)((color.B * amount) + backColor.B * (1 - amount));
        return Color.FromRgb(r, g, b);
    }

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        //Assumes the percent property to be an int.
        int input = (int)value;
        Color red = Colors.Red;
        Color yellow = Colors.Yellow;
        Color green = Colors.Green;
        Color color;
        if (input <= 50)
        {
            color = Blend(yellow, red, (double)input/50);
        }
        else
        {
            color = Blend(green, yellow, (double)(input - 50) / 50);
        }
        return new SolidColorBrush(color);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

Which you could use like this:

<ListView>
    <ListView.Resources>
        <vc:PercentToBrushConverter x:Key="PercentToBrushConverter"/>
    </ListView.Resources>
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Progress">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <!-- An indicator ellipse as suggested by Neil Barnwell -->
                            <Ellipse Height="16" Width="16" Fill="{Binding change_percent, Converter={StaticResource PercentToBrushConverter}}"/>
                            <TextBlock Margin="5,0,0,0" Text="{Binding change_percent}"/>
                        </StackPanel>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <!-- ... -->
        </GridView>
    </ListView.View>
</ListView>

How to do the xmlns declaration:

You need to define the class in some namespace:

namespace MySolution.ValueConverters
{
    public class PercentToBrushConverter : IValueConverter { /*...*/ }
}

This namespace can be mapped in the Window or any other parent control:

<Window ...
    xmlns:vc="clr-namespace:MySolution.ValueConverters">

This maps the MySolution.ValueConverters namespace to the vc prefix. For some more reference see MSDN.

H.B.
  • 166,899
  • 29
  • 327
  • 400
  • I know I'm asking for too much but I don't know how to do that ? – Mouayad Al ZEIN Apr 28 '11 at 08:57
  • I'll try to expand on my answer, it might take a while though. – H.B. Apr 28 '11 at 08:57
  • actually no , but I can google for that , I guess its not so hard – Mouayad Al ZEIN Apr 28 '11 at 09:27
  • Have a look at [this article on MSDN](http://msdn.microsoft.com/en-us/library/ms752059.aspx#custom_prefixes_and_custom_types_in_xaml). – H.B. Apr 28 '11 at 09:29
  • That's why i asked whether you know how to deal with xml namespaces. You need to define a `xmlns` in some parent control which points to the namespace that contains the `PercentToBrushConverter` class. e.g. `xmlns:vc="clr-namespace:MyApplication.Converters"` – H.B. Apr 28 '11 at 09:45
  • help me for the last time :) and I promise not to bother you anymore my solution name is (Cham Securities Ticker) and the class I created is named (PercentToBrushConverter) , what should I write in my xmlns ? – Mouayad Al ZEIN Apr 28 '11 at 09:52
  • I cannot know that from this info alone, i added some more info to my answer, hopefully that makes it more clear. – H.B. Apr 28 '11 at 09:59