user683812
user683812

Reputation: 31

Setting a GridView's colour in WPF via code

I've been searching for quite a long time how to do this. I don't know how to set the colour of a row item in the GridView (WPF) using code I don't want an example in XAML

My data comes from me loading & pulling apart an XML file. I then put it into a small class with properties and those are bound to the column to populate the data. Later, it can begin some functions on the table's data. Because this takes at some times over 10 minutes it's on a thread & I would like to colour the rows I've completed parsing depending on the result. (IE: Red for HTTP error, Orange for XML parsing error ect...)

This is the GridView's XAML:

<ListView Name="RepoListView" Margin="0,22,0,0">
  <ListView.View>
    <GridView AllowsColumnReorder="True">
      <GridViewColumn Header="Title" DisplayMemberBinding="{Binding title}" />
      <GridViewColumn Header="URL" DisplayMemberBinding="{Binding url}" />
      <GridViewColumn Header="Subscriptions" DisplayMemberBinding="{Binding dlc}" />
    </GridView>
  </ListView.View>
</ListView>

I am then parsing the data using the url column. I am currently changing the selected item as I go through. I want to know if theres something I can do to change the specific item. Let's assume I'm on row 500:

I use: setSelected(i) which uses Dispatcher to safely change the selected row. Is there anything I can do to change the colour as well? I've been trying for hours to find a solution.

Thanks

Upvotes: 1

Views: 2374

Answers (1)

brunnerh
brunnerh

Reputation: 184296

I would probably go for a binding approach, code behind is ugly. Create a property with an error enum and create a DataTemplate or Style in which you bind the background to said property.

Edit: Example...

In your class:

public enum ParsingStatus { None, Completed, XmlError, HtmlError }

private ParsingStatus _status = ParsingStatus.None;
public ParsingStatus Status
{
    get { return _status; }
    set
    {
        if (_status != value)
        {
            _status = value;
            NotifyPropertyChanged("Status");
        }
    }
}

Then you can either bind to the background property using a converter like this:

public class ErrorToBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Employee.ParsingStatus input = (Employee.ParsingStatus)value;
        switch (input)
        {
            case Employee.ParsingStatus.None:
                return null;
            case Employee.ParsingStatus.Completed:
                return Brushes.LightGreen;
            case Employee.ParsingStatus.XmlError:
                return Brushes.Pink;
            case Employee.ParsingStatus.HtmlError:
                return Brushes.Yellow;
            default:
                return null;
        }
    }

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

And the respective XAML:

<Window.Resources>
    <local:ErrorToBrushConverter x:Key="ErrorToBrushConv"/>
    ...
</Window.Resources>
    ...
        <ListView ItemsSource="{Binding Data}">
            <ListView.ItemContainerStyle>
                <Style TargetType="{x:Type ListViewItem}">
                    <Setter Property="Background"
                            Value="{Binding Status, Converter={StaticResource ErrorToBrushConv}}"/>
                </Style>
            </ListView.ItemContainerStyle>
            ...
        </ListView>

Or you only specify a Style and do the switch on the status using triggers:

<ListView.ItemContainerStyle>
    <Style TargetType="{x:Type ListViewItem}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Status}" Value="XmlError">
                <Setter Property="Background" Value="Pink"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding Status}" Value="HtmlError">
                <Setter Property="Background" Value="#FFFFFF66"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding Status}" Value="Completed">
                <Setter Property="Background" Value="LightGreen"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</ListView.ItemContainerStyle>

(Using triggers was suggested by Robert Rossney, as you can see it is quite short and requires no code behind at all, i cannot really think of any downsides to this and i have no idea why i did not do it like this in the first place...)

Which looks like this with the converter (the yellow of the trigger-method is more suitable):
A colourful ListView

Upvotes: 3

Related Questions