WPF DataGrid – Gotchas
The WPF DataGrid is a monster of a control (just like the DataGridView in Windows Forms is), but some things drive me crazy. They baked a lot of functionality into this control – and then they skipped easy functionality because… well, who knows. Below, I’ll present a few of the ones, I’ve dealt with:
CellAlignment – what, where – who?
I simply do not understand why this concept didn’t make it. I would have thought the syntax should be like this:
<DataGrid ….><DataGrid.Columns>
<DataGridTextColumn CellAlignment=”MiddleCenter”
….But no – this wasn’t done. You can go different routes from here:
- Full control – DataGridTemplateColumn, set the appropriate CellTemplate and CellEditingTemplate.
- Middleground – Set CellStyle on the Column and exchange the Template with something that can align properly
- Simplest – Set CellStyle as #2 but set TextBox.TextAlignment and TextBlock.TextAlignment to your desire.
There are problems with all three:
#1 Two templates per column you want to align right or center…
#2 Good luck selecting that one with the mouse, if you align center on an empty cell… And it breaks layout
#3 Only works horizontally – vertical? You’re SOL.Sorting and editing
If you use only one or the other – everything works perfect, but when you mix them… you’re bound for trouble. If the DataGrid is in edit mode – and you update the sorting or update the observable collection, you get exceptions.Interfaces in ItemsSource
If your DataContext has an ObservableCollection<ISomeInterface> property and you bind to that – the NewItemPlaceHolder will only be shown if you have items in the collection – if it is empty, adding new items cannot be done unless you do it programmatically. This is due to the DataGrid not knowing which class to instantiate and thus deciding that it is impossible. IMHO, I would be happy to supply the correct item, if only the DataGrid would let me in an eventhandler… The solution is not to declare the collection with interfaces, but use concrete implementations with a default no-argument constructor if you need the AddNew functionality.Properties and bindings
Don’t get me started here – in version 4.0 they introduced BindingGroups which disables UI-updates outside the editing cell until the row is committed. This is bad news, if you have one column that depends on another – or just a calculated sum that should update as the basis changes. See here how to disable it. Also, it seems to me that which properties got to be Dependency Properties was due to asking a magic 8-ball. Header-property is not (it is on GridViewColumn, ContentControl etc.) although something has happened to it in version 4.0, so it’s bindable, but the binding is broken…ComboBoxColumn
How they managed to decide which convenience properties made it must been after a hard night of partying – ItemsSource and SelectedItemBinding made it, but ItemTemplate didn’t – and if you set it in the ElementStyle remember to set it in the ElementEditingStyle as well… And somehow ItemsSource is broken if your datasource is directly on the bound item – so {Binding SomeProperty} doesn’t work but {Binding SomeProperty,Source={StaticResource SomeDataSource}} does.Naming
Let’s just say… uhm… WTF? TextBoxColumn: Binding should probably have been DisplayMemberBinding or TextBinding or some such. ComboBoxColumn: SelectedItemBinding, SelectedValueBinding and then ItemSource (which also accepts a binding)AlternateBackground
Since all ItemsControls get an alternation count in .Net 4.0 – I believe they should have discarded this property. Yes, it is easy to use, but it is more limited than using AlternationCount and ItemsControl.AlternationIndex as you can only have two differnet backgrounds (the other solution can have as many as you like – like highlighting every fifth or tenth row for easy visual counting). Having two conflicting ways of doing essentially the same thing is not a good thing as it will confuse more than help – I haven’t tried what happens if you use both, but I would think that it would look strange…
These things aside – there is a lot of nice functionality out of the box, but I really would have liked them to clean up some of the messes before introducing it into the framework. Now we will forever (well… IT and forever) have to live with Binding in TextBoxColumns due to backwards compability…