Bruno Silva
Bruno Silva

Reputation: 147

Changing the color of rows in a DataGrid in Wpf

I am having problems changing the color of the DataGrid rows, I use the following function

int i = 0;
private void gvDados_LoadingRow(object sender, DataGridRowEventArgs e)
{
   DataGridRow rowContext = e.Row;
   if (rowContext != null)
   {
      string Situacao = dt.Rows[i]["Situacao"].ToString();
      if (Situacao.Equals("V"))
      {
         SolidColorBrush brush = new SolidColorBrush(Color.FromArgb(100, 255, 104,0));
         rowContext.Background = brush;
      }
      else
      {
         SolidColorBrush brush = new SolidColorBrush(Color.FromArgb(100, 255, 232,0));
         rowContext.Background = brush;
      }

      i++;
   }
}

So far so good, I can adjust the colors according to what I want, the problem in question is when I use the Horizontal Scroll Bar to go down the registers or climb, then all colors are misconfigured appearing at random. How can I solve this problem so things do not change when scrolling?

Upvotes: 1

Views: 9757

Answers (1)

Sach
Sach

Reputation: 10393

The LoadingRow event of DataGrid fires whenever a Row is 'instantiated'. When you scroll rows go in and out of scope, and this event is fired repeatedly for each row that 'loads' into the view.

Assuming that your DataGrid is loaded at some event such as a button click or some such action, you probably need to do the coloring of rows when you actually load the data into your DataGrid, preferably using a function written for that, and later on call the function again if content is changed and you want to display colors according to changed content.

Something like this:

// This could be a button event, or some other event after which you load data into the DataGrid
void ButtonLoadEvent()
{
    foreach(Datagrid Row)
    {
        FunctionThatChangesRowColor(Row);
    }
}

EDIT:

Actual code on how to get DataGrid rows and apply coloring. This is a modified version of your coloring logic, and here each row is colored depending on whether its row index is odd or even. You may replace this with your code.

Pass the entire DataGrid to this function.

private void ColorRow(DataGrid dg)
{
    for (int i = 0; i < dg.Items.Count; i++)
    {
        DataGridRow row = (DataGridRow)dg.ItemContainerGenerator.ContainerFromIndex(i);

        if (row != null)
        {
            int index = row.GetIndex();
            if (index % 2 == 0)
            {
                SolidColorBrush brush = new SolidColorBrush(Color.FromArgb(100, 255, 104, 0));
                row.Background = brush;
            }
            else
            {
                SolidColorBrush brush = new SolidColorBrush(Color.FromArgb(100, 255, 232, 0));
                row.Background = brush;
            }
        }
    }
}

But that too is not a perfect solution seeing as you're using WPF, not WinForms. One suggestion I have is to go for a WPF DataBinding approach, and let the XAML do the color coding for you.

This is a sample of code that I often use for this purpose.

WPF Approach Code:

<Window x:Class="ColorLibrary.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ColorLibrary"
        mc:Ignorable="d"
        Loaded="Window_Loaded"
        Title="MainWindow" Height="500" Width="400">
    <Window.Resources>
        <Style TargetType="{x:Type DataGridRow}">
            <Style.Setters>
                <Setter Property="Background" Value="{Binding Path=Code}"></Setter>
            </Style.Setters>
        </Style>
    </Window.Resources>
    <Grid>

        <!-- Stuff -->

        <DataGrid Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2"
                  Name="dgvColors"
                  AutoGenerateColumns="False"
                  Margin="4">
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="#" Width="Auto">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Num}" VerticalAlignment="Center" Padding="3"></TextBlock>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn Header="HTML Code" Width="Auto">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Code}" VerticalAlignment="Center" Padding="3"></TextBlock>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn Header="Color" Width="*">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Color}" VerticalAlignment="Center" Padding="3"></TextBlock>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

    </Grid>
</Window>

In,

<Setter Property="Background" Value="{Binding Path=Code}"></Setter>

Code is a property in a class which contains the color name to be used to color the cell.

Then we have an ObservableCollection of that class objects. You need to set this property (of each item in the ObservableCollection) to the color you need each row to be displayed in.

Upvotes: 3

Related Questions