Question

How do you change the color of the silverlight datagrid rows?!

I've tried this but it doesn't seem to work how I want it to...Random rows get colored incorrectly:

 void dataGrid1_LoadingRow(object sender, DataGridRowEventArgs e)
        {
            var c = e.Row.DataContext as Job;
            if (c != null && c.Status.Contains("complete"))
                e.Row.Background = new SolidColorBrush(Colors.Green);
            else
                e.Row.Background = new SolidColorBrush(Colors.Red);
        }
Was it helpful?

Solution

Microsoft Documentation :

To improve performance, the EnableRowVirtualization property is set to true by default. When the EnableRowVirtualization property is set to true, the DataGrid does not instantiate a DataGridRow object for each data item in the bound data source. Instead, the DataGrid creates DataGridRow objects only when they are needed, and reuses them as much as it can. For example, the DataGrid creates a DataGridRow object for each data item that is currently in view and recycles the row when it scrolls out of view.

source : http://msdn.microsoft.com/en-gb/library/system.windows.controls.datagrid.unloadingrow.aspx

this explains the behaviour you have been experiencing

the proper (though not easier I admit) solution being, hence, to use the UnloadingRow event to unset the style you had set.

OTHER TIPS

I had this same issue and figured it out after making a minimal test and some deductive reasoning!

Basically the solution is to ALWAYS make sure you set the background color (or any style in fact). Don't assume any defaults for row styling. I was assuming a default of white - which is a reasonable assumption but was not actually the case.

More details:

It looks like the runtime reuses instances of the Row class when rendering multiple rows. I haven't verified this at all but judging from the symptoms it seems like that must be happening.

I had only one or two rows that ought to be colored differently. I was seeing randomly colored rows when scrolling up and down.

Here is my test class i made. Every fifth row is supposed to be red and italic.

You'll see a couple lines commented out (that set a default of non-italic and white background). With these commented out - if you scroll up and down you will see a lot of red!! This is because the row objects are being reused. If you make the window smaller and then maximize it some of the white will come back. Probably garbage collector collecting rows it doesn't think you'll need any more after having made the window smaller.

As i said above the solution is to always specify styles for defaults and don't assume any defaults.

public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();

        dataGrid1.ItemsSource = Enumerable.Range(0, 50).Select(x => new Person()
        {
            FirstName = "John",
            LastName = "Smith",
            ID = x,
            Delinquent = (x % 5 == 0)     // every fifth person is 'delinquent'
        });
    }

    private void dataGrid1_LoadingRow(object sender, DataGridRowEventArgs e)
    {
        var person = (Person)e.Row.DataContext;

        if (person.Delinquent)
        {
            e.Row.Background = new SolidColorBrush(Colors.Red);
            e.Row.Foreground = new SolidColorBrush(Colors.White);
            e.Row.FontStyle = FontStyles.Italic;
        }

        else
        {
           // defaults - without these you'll get randomly colored rows
           // e.Row.Background = new SolidColorBrush(Colors.Green);
           // e.Row.Foreground = new SolidColorBrush(Colors.Black);
           // e.Row.FontStyle = FontStyles.Normal;
        }

    }

    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int ID { get; set; }
        public bool Delinquent { get; set; }
    }
}

I was after this:

void dataGrid1_LoadingRow(object sender, DataGridRowEventArgs e)
        {
            DataGridRow row = e.Row;
            var c = row.DataContext as Job;         
            if (c != null && c.Status.Contains("omplete"))
                e.Row.Foreground = new SolidColorBrush(Colors.Green);
            else
                e.Row.Foreground = new SolidColorBrush(Colors.Red);
        }

The best way to do this is to change the RowStyle on your DataGrid. This requires a lot of xaml, but you can just copy that from here and change a few styles in it.

Also, if you need to change the row color based on the row data, you can add a binding in the Style to a Brush property on your data.

They opened Reflector and took generic.xaml for the DataGrid from System.Windows.Controls.Data.dll, and then wrote some new xaml to change it.

It works for me. =)

private void MyDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
    {
        var row = e.Row.GetIndex();
        if (row % 2 == 0)
        {
            e.Row.Background = new SolidColorBrush(Colors.Red);
            e.Row.Foreground = new SolidColorBrush(Colors.White);
            e.Row.FontStyle = FontStyles.Italic;
        }

        else
        {
            // defaults - without these you'll get randomly colored rows
            e.Row.Background = new SolidColorBrush(Colors.Green);
            e.Row.Foreground = new SolidColorBrush(Colors.Black);
            e.Row.FontStyle = FontStyles.Normal;
        }
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top