Archive for November, 2008

WPF Toolkit DataGrid, ColumnHeader Style and Blend 4

I’ve spent the better part of the day trying to figure out how to style the column headers of my WPF Toolkit datagrid through Microsoft Blend. Blend is a great tool and I couldn’t imagine trying to do a WPF application without it; however it is still immature and this could be why I found it so difficult to figure out. It could just be that I’m new to Blend, WPF, and XAML and still have a lot to learn.

I’ll spare you the agony I suffered this morning and jump right into the solution.

We have a pretty basic style for the datagrid at the moment. You’ll have to forgive the visual obfuscation.

Changing the the column header style looked pretty obvious in Blend. The menu walks me through the steps to create a resource for the header style.

Give the style resource a name. In this case I am going to show a pivoted set of data with a set of frozen columns on the left and columns that accept entering data on the right. I give it the name I want and choose its destination.

When the steps are complete, I have a style in the resources dictionary for my window, but something is missing.

I’m not sure if I’m missing a step, but the target type of the resource is the generic IFrameInputElement type. It doesn’t provide any properties to set in the designer.
If I look at the XAML that was created, it doesn’t give it a type.
<Style x:Key="EnterableColumnHeaderStyle"/>

The examples I’ve been seeing have a TargetType property to allow for the attached properties to work properly. I got ahead and add my TargetType property.

As you can see, I’m still learning WPF and XAML.  ReSharper steps in and offers to help out a bit. I am glad to let it. It adds the proper namespace to the resource:

<Style x:Key="EnterableColumnHeaderStyle" TargetType="primitives:DataGridColumnHeader">

It also creates the namespace directive:

I don’t really like the namespace alias, so we’ll change it with the help of ReSharper.

Blend now knows our target type and gives us all the properties we could want to style.

We can do whatever we want with the column header now.

And, just as we’d expect, we get our new style.

We can also apply a style to a particular column.

<wpfToolkit:DataGridTextColumn x:Name="FirstColumn"   Header="Something"  HeaderStyle="{StaticResource FrozenColumnHeaderStyle }" >

A Tale of Inconsistency 1

So in the hard times of our economy, companies cut back on non-essentials. We’ve recently gone from two coffee pots to one.* We have anther pot with an orange handle, but I can’t see the logic in drinking from that one. Only one pot means all those snaky people who leave 2oz of coffee for the person behind them holding a 6oz cup are twice as effective. You can no longer combine the two 2oz pots and get a somewhat satisfying cup of coffee.

Yesterday I was the unfortunate one who came across an empty pot. So after mentally cussing out whomever left it, I started a new one and went to the next floor where I was able to grab the last full cup. Yes! Being the good boy I that am I started yet another pot. I reached into the drawer where the coffee is kept, made the pot and started to leave. As I was leaving the room the label I tossed in the trash caught my eye. There was a little flash of green on the package. I went and looked closer. This floor kept the regular and decaff coffee in opposite drawers as the superior floor above. Luckily I caught my mistake, trashed the pot that was already started and made a proper pot. The poor souls who would have failed to receive their liquid wake up call would weighed against my karma.

It holds true in life, as well as programming. Consistency matters. We develop routines that are habitual and difficult to break. Just as the coffee was always in the same drawer, the parameters are always in the same order. Taking extra care to follow some de facto convention could save slip ups like this.

* The reduction was most likely not related to cut backs, but rather just ended up being broken; however, not replacing it may be related to cut backs.

ReSharper Tip of the Day: Put into ‘using’ construct. 0

There has been some debate if you need every IDisposable should be disposed. From the documentation IDisposable is used to clean up any unmanaged resource.

Use the Dispose method of this interface to explicitly release unmanaged resources in conjunction with the garbage collector.

OK. That’s fine. I totally agree with that until I see DataTable is derived from a class, MarshallByValueComponent, that implements IDisposable. Does that mean DataTable has unmanaged resources? Any way, on to the tip.

ReSharper notices when an object is created that implements IDisposable and it can automatically wrap the usage in a using block. Say you have the following code:

…and want to put it in a using block. Trusty ALT+Enter steps in a gives you the following options:

It is creates a nice using block around the object and all of its usages.

What would really be nice is we could create a warning when we see ourselves using an IDisposible without calling Dispose. That might be more difficult than finding one outside of a using. We could be calling Dispose in a try/finally or somewhere else.

WPF Grid and Read Only Columns 3

In an attempt to provide a total summary column in a WPF data grid, I attempted to bind a read only column of a DataTable to a DataGridTextColumn of the WPFToolkit data grid.

Initially, I tried to do the way I’ve been doing every other column.

<wpfToolkit:DataGridTextColumn
     Header="Total"
     DataFieldBinding="{Binding Total}"  />

Unfortunately that gives us the following error:

A TwoWay or OneWayToSource binding cannot work on the read-only property ‘Total’ of type ‘System.Data.DataRowView’.

OK, that makes sense, we should just adjust the mode of the binding and try again.

<wpfToolkit:DataGridTextColumn
     Header="Total"
     DataFieldBinding="{Binding Total,Mode=OneWay}"  />

….but we get the same error. After a few quick Google searches, I found someone else that already pointed out the issue and a possible workaround.

ReadOnly columns is missing from the CTP, but that is not a huge problem, you can easily accomplish ReadOnly behavior by using DataGridTemplateColumns and replacing the templates with read-only controls ( like TextBlocks).

A quick change of the column to a DataGridTemplateColumn and it looks like we are off to the races.

<wpfToolkit:DataGridTemplateColumn Header="Brand">
    <wpfToolkit:DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=Brand,Mode=OneWay}" />
        </DataTemplate>
    </wpfToolkit:DataGridTemplateColumn.CellTemplate>
</wpfToolkit:DataGridTemplateColumn>

NOTE: After another bit of searching on the web, the WPF Toolkit – October 2008 was released last week. This negates the need for the workaround for read only columns.

<wpfToolkit:DataGridTextColumn
     Header="Total"
     Binding="{Binding Total}"
     IsReadOnly="True" />