views:

4880

answers:

3

Hey! 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);
        }
+1  A: 

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);
        }
Goober
If this works for you, you should accept it as the answer.
kersny
I don't see how this fixes things. Unless a clear problem can be presented the solution given this whole question should be deleted.
AnthonyWJones
@Kersny Can't accept your own answer for 2days. @AnthonyWJones, people like you annoy me, grow up.
Goober
@goober - can you explain what the difference is here. i am getting randomly colored rows as you described. its making no sense. i cant see how it isn't a bug in silverlight. how can changing 'complete' to 'omplete' possibly fix this.
Simon_Weaver
@goober - ok i see what you did here. i still don't see how it can fix it in the context of my findings below. i think perhaps your original code was 'paraphrased' from what you actually had
Simon_Weaver
@kersny no - he should accept MY answer :-)
Simon_Weaver
A: 

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; }
    }
}
Simon_Weaver
+1  A: 

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 add set.

David