Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Changing the background color for one or more columns in a Silverlight DataGrid

0.00/5 (No votes)
2 Jan 2010 2  
Column.BackgroundColor = Yellow? I wish.

Introduction

This is something you would think would be pretty simple, but it isn't, unless I'm missing something. I thought I'd write a little step by step of how I arrived at the solution I came up with in case I took a more difficult path than I needed to and someone can point out where I took a wrong turn.

Background

Here is the basic XAML for a DataGrid and what it looks like in the browser. You have sorting, validation, and two way binding, which is pretty nice:

1-code.jpg

1-result.jpg

The dilemma

All this works fine and until someone says they want the first two columns read-only and they want the third column with a yellow background so the user can easily tell which columns are editable. "No problem" you say, whereupon you become perplexed at the curious lack of a Background or a BackgroundColor property in the text column:

2-code.jpg

You, being an industrious person not easily discouraged by such trifles, decide to turn to the templated cell to gain more control over what is going on, making a template for the read only view (a TextBlock) and for the edit mode (a TextBox). The TextBox does have a Background property, sweet success! But the TextBlock doesn't have a Background property, crushing defeat. To add insult to injury, now sorting and validation don't work either. But, we do have a different background color in edit mode, so that is progress of a sort.

3-code.jpg

3-result.jpg

Utilizing your finely honed Google-Fu, you correct the two issues just created, with the following:

4-code.jpg

And then, if the TextBlock doesn't have a Background property, let's just throw something behind it that does, like a Border, and we should be all done, right?

5-code.jpg

5-result.jpg

Well, that's pretty close, but now, as we mouse over the rows, we don't see the nice highlight effect that was there, and it just, generally, doesn't look that great. It would be nice if we could still have the nice UI cues that were there in the first place, but just, well, with a different background color. At this point, you may start pondering a dive into the visual state manager and animations, but as you watch everyone else leaving the office, you start wondering why you've been spending all day messing with the background color of a column.

Ignoring this irrelevant piece of information, you sense inspiration, and think, "Ah! if the background were only partially visible, the existing animation might be more visible, and no additional work would be needed!"

6-code.jpg

Which is kinda true... Except now, the font is slightly transparent as well, and no amount of font bolding or manual setting of opacity seems to help:

6-result.jpg

7-code.jpg

Cursing the stars and heavens while simultaneously pounding your keyboard with your elbows, you accidentally stumble into this, which does work! Eureka, you have done it!

8-code.jpg

8-result.jpg

Except... You feel kind of dirty because in order to change the *&#$^*&^$% background color, you have exploded one line of XAML into 15, which seems excessive. Furthermore, there is great redundancy in the name of the column, the background color used, and you are going to have to copy and paste this multiple times for multiple columns. You briefly consider using a style, but that will only get you so far since you'd still have to specify the two templates for each column using this method.

A voice in the back of your head is telling you to set fire to this DataGrid and look into vendor grids, but no, you won't be undone by these minor issues.. You will find a way to beat this issue into submission. Shortly before running out of curse words and keyboards, you arrive at the final solution which looks and acts exactly like how you would expect it to:

final-code.jpg

final-result.jpg

public class DataGridTextColumnExtended : DataGridTemplateColumn
{
    public string Background { get; set; }

    public string BindingProperty
    {
        set
        {
            if (value == null)
                throw new ArgumentNullException("BindingProperty");

            //otherwise sort won't work on template column
            base.SortMemberPath = value.ToString();

            CellTemplate = (DataTemplate)XamlReader.Load(@"
             <DataTemplate 
               xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>
             <Border Background='" + Background + @"' Opacity='.5' />
             <TextBlock Text='{Binding Path=" + value + @"}' Margin='4' />
             </DataTemplate>
             ");

            CellEditingTemplate = (DataTemplate)XamlReader.Load(@"
             <DataTemplate 
               xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>
             <TextBox Background='" + Background + @"' Text='{Binding 
             NotifyOnValidationError=True, ValidatesOnExceptions=True, 
             Path=" + value + @", Mode=TwoWay}' />
             </DataTemplate>
             ");

            _BindingProperty = value;
       }

       get
       {
           return _BindingProperty;
       }
    }
    private string _BindingProperty = null;
}

Enjoy!

Points of Interest

No actual keyboards or desks were harmed in the making of this article.

Also, if you have a cleaner way of creating the custom column with the code being in a separate XAML file instead of C# (while keeping the usage XAML the same), I'd love to hear about it.

History

  • 2-Jan-2010 - Initial version.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here