WPF DataGrid – Gotchas

Skrevet - Sunday, July 18th, 2010 kl. 1:55 | Kategori - * Rants.

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…

Approximately TestDriven

Skrevet - Saturday, July 17th, 2010 kl. 11:49 | Kategori - * Coding, * Rants, English posts.

As it might shine through in my previous posts – I have a pragmatic view on TDD. I understand why tests are important – I do tests, but I don’t test everything – maybe I approach 15% test-coverage. I chose to make ERP-systems my speciality – and I land at lousy 15% coverage?

Many would say that a SOA-based ERP-system has so much complexity and is so intricate that it should be near 100% covered in tests. I disagree (not surprisingly). Having built these monsters (albeit not distributed, but as a standard rich client) for three years has taught me a lot. We have gone through various stages of TestDriven:

We started out doing 100% TestDriven – we set the mark at 80% test coverage – and all interfaces should be built using TestDriven methodologies. We also decided that all classes should uphold SOLID principles – solid (haha) reasons should be present if one of the principles were violated. This period lasted about 6 months – and then came the first large round of re-factorings…

It showed us a few things – first, don’t test simple properties – they catch no errors, we had none regressions in that area – and they only caused us problems when re-factoring as the tests were brittle.

Then we proceeded doing fewer tests and instead focused on integration tests – and we tried to do acceptance testing from UI down to the database. We spent a lot of time here… and learned a few more things – first, UI tests are expensive and they are extremely brittle – a change in UI automation keys would break it, a simple change in docking could break them and most importantly: Complex WPF datatemplating is almost impossible to test in a meaningful way.

Then we introduced the Model-View-ViewModel pattern in all UI-centric functionality – and now the tests started paying off. All the ‘goup’-code collected in one place and testable. Hooray!

That left us with doing 3 kinds of tests:

The last one might seem curious – but presenters are the ‘mother’-objects in these scenarios – they tie all the other classes together – and if they resolve – all other elements have been registered correctly. And about 20% of the few bugs we had were forgetting to register one of the dependencies correctly.

The problem is that a new developer cannot do it the same way. Remember, this is the result of three years of experience and we now develop in a way that is much like TestDriven in that classes are introduced in the same way (“oops, not a part of this class’ responsibility – new class”). And we wouldn’t be able to do it this way if we hadn’t felt the pain early on.

The guy who introduced patterns, principles and TDD/BDD/DDD to me once said something I think is truth: “If you haven’t felt the pain of doing things the wrong way – you’ll see the right way as unnecessary friction”. And to learn to do things better – you need to approach it with in a certain way – which is all about taxonomy levels:

When beginning – you need to adhere strictly to the rules.
When advancing – you can start applying the rules when necessary.
When competent – you don’t need the rules.
When omnipotent – you make the rules.

If you skip one of the levels – you are bound to f#¤% up. At my current programming level – I’m somewhere around competent in the areas I specialize in. I still have epiphanies when I look at other peoples code going “Ahh, of course – that’s so simple that I should be spanked for not seeing that right away”, but I no longer think of the principles and patterns as rules. I apply some of the logic of the patterns to my classes when it is necessary – but sometimes the solution is a hybrid between two patterns – or only parts of a pattern.

So, I accept the rules of Test Driven Development, and I accept that you have to walk the path to find the balance, but I disagree in that everything has to be driven by tests. However, your development should be testable – thus, the classes need to be built the same way as they would have been if you had done TDD.

Prototyping vs. doing ‘real’ developement

Skrevet - Wednesday, July 14th, 2010 kl. 0:32 | Kategori - * Coding, * Rants, English posts.

I’m currently making a prototype where I have to show how the final application will look. That means, I have to build basically everything, I would normally build for the ‘real’ application (data, styling and command-logic). This is not my preferred way of working – normally I would build it incrementally – one functionality at a time and then at some point introduce styling – but I understand the reasoning. We need the marketing material some time before we have a working product. And we need early feedback to ensure that we get qualified feedback as fast as possible.

At first, I tried going about it, as I would with ‘throw-away’-code – heavy code-behinds – direct instantiating everything in Resources-tags and generally introducing messes all over the place. This worked well for about two days. At this time, I sat down and looked at the mess… and realized a few things.

Motivation wasn’t there
I actually lost a lot of motivation going about coding something I knew was going to be thrown away. Just looking at horrible code was enough to make me go… “Arhh… I’ll work on it tomorrow”. Having practised heavy re-factorings for 2 years has made me appreciate elegant code – and my fingers were itching at re-factoring this horrible mess. (And when I say horrible mess – I’m not sure how other developers would characterize it, but it’s certainly a lot under my normal quality).

Coding speed was actually slower
This may seem counter-intuitive, but it is actually true. Using ReSharper, I crank out code which uphold most of of the SOLID principles without needing re-factorings since I’m actually coding stuff, I’ve tried before. I have a fairly good idea when it’s time to introduce a base-class and which responsibilities go where. And having no IoC container to handle the wire-up – I was writing a lot of code just to get my buttons to do something. Also, using WPF – a lot of styling is relying on common interfaces and TemplateSelectors on top of ViewModels – and that is extremely fast compared to rolling XAML to e.g. hand-craft a toolbar. Also, I spend a fair amount of time in the debugger, because I made rookie binding errors.

Friction was at an all time high
Adding the first 2-3 features went fast, the next 2-3 went okay and then it started grinding to a halt. It was a bit of an eye-opener how much friction is reduced by using good OO-practises and coding to SOLID. Normally in production code, adding a feature is a matter of adding an interface – and not changing or replacing an existing one. In the prototype this was just not true – I continually had to rewrite a bit of functionality to take into account this new situation.

So, the solution has been to do production code instead, albeit with a slightly tweaked production method. I call it scaffolding code. First, I created all the modules, we have on the drawing board and introduced a few buttons here and there. Then came a styling round to make it pretty. Then I added one of the main screens with domain objects that are pretty much stupid DTO’s. Again, styling. Next a new main screen… styling – you get the picture. This means that all data-access is in-memory, validation is non-existent and a lot of functionality is represented by a button alone.

So far, I have two ‘working’ screens and about 5 ViewModels that are pretty much doing what they will be doing come live-time. I have ‘real-looking’ data to simulate what it will look like in production – and I’m blazing through functionality. And as my base-classes are starting to pay off – each new feature is actually faster than the first few features. So, I’m picking up speed (eventually, it will plateau, but that’s okay).

It’s funny how sensitive, I’ve become when it comes to building it ‘right’. Some features are cheating a bit – some edge-cases are missing from the selectors and so on, but overall I’m getting pretty excited about this project! It seems I’ve hit a structure that will be there for the long haul.

The gobbo got a new job!

Skrevet - Friday, July 9th, 2010 kl. 20:56 | Kategori - * Coding, * Jobhunting, English posts.

Come 1st of August, I start a new job at NotaPlan ApS as a C#/WPF developer. I will be joining a few different projects in a tight team of 4 – and overall, I hope I can add some experience in business-logic – and of course my NHibernate and WPF skills will be put to good use. I was head-hunted for the job – sort of – after I held a course for two of the developers at NotaPlan. One of them is now my new boss…

The reasons I quit my job at TransSoft are many, but ultimately not something, I feel is important to share. What’s important is that I’m really excited about the change and look forward to getting my fingers dirty!

How people always try to do things the hard way with WPF

Skrevet - Tuesday, July 6th, 2010 kl. 22:00 | Kategori - * Coding, * Rants, English posts.

I lurk a lot on StackOverflow - it sometimes strikes me how hard people try to make their problems. Instead of using a simple solution, they will over-engineer it until it becomes impossible to do what they’re trying to accomplish. If you are trying to bind to the parent control via templatebinding and do a trigger that is dependant on the parent control being a ContentControl – you are creating trouble for yourself down the road.

I think, all the problems stem from trying to force a solution into XAML or more eloquently trying to solve all problems using the hammer. It may be that the WPF technology is so new – or it may just be the fact that people are stupid… but they tend to forget that ‘Simple is better’ and ‘use the appropriate tool for the task at hand’. Common examples follow:

1. “I want to have these default values set on all Buttons”
Use a Style in App.xaml with key-tag blank and set all the properties.

2. “I only want some buttons to have this default style”
Inherit from Button (e.g. StyledButton) and do 1.

3. “I want to use data from a parent data object in my childTemplate”
Put parent data object into ObjectDataProvider and bind to that or make an extra property on your viewmodel (viewmodels are cheap compared to maintaining a complex binding) – stop using relative bindings!

4. “I want to inherit from another style and then just set these few extra properties”
Don’t. It is not a violation of DRY to repeat property setters in different styles.

This advice might seem weird coming from a guy that specializes in the “new and fancy” world of WPF, but the problem with all frameworks is that they always provide edge-case functionality. Functionality that might seem nice on the surface but will bite you where it hurts if you use it. RelativeBindings might seem like a good idea – but when I try to use them, the views will continue to haunt me when I do refactorings or re-create a layout. They are pain-point that I would rather be without. And of course – no rule without exceptions – but for a complete ERP solution, I have managed without them. Having styles inherit from each other might also seem like a good idea – but the problem is that come 6 months – you now have an(or more if you have inheritage styling trees) extra place(s) to look for that setter that is causing you headaches on top of local values, inherited values, bound values etc.

Just because you are in XAML doesn’t exempt you from using good ol’ OO-techniques!

En lille prototype

Skrevet - Monday, July 5th, 2010 kl. 23:58 | Kategori - * Kodning, Danske indlæg.

Min hustru har en større interesse i gamle billeder og har i en periode spurgt om jeg ikke kunne lave et lille simpelt galleri til at holde styr på data på disse billeder. Jeg lider af NIH-syndromet (Not Invented Here), så jeg satte mig ned og kastede lidt kode efter det – og her er resultatet – SimpleGallery.

Den største udfordring var faktisk at undgå at lave koden for kompliceret. Når man er vant til at lave store komplekse løsninger, er det lidt den omvendte verden at lave små applikationer, hvor alt ikke behøver et interface fordi det alene tilføjer kompleksitet til noget, der ikke bør være komplekst (og ja, det kløede flere gange i fingrene, for at implementere interfaces over det hele). NHibernate sneg sig ind mens jeg kiggede væk – jeg gad ikke sætte mig ind i DataSets igen (er nogle år siden jeg sidst brugte dem). Funktionaliteten er til at overse:

Så, efter et par timer eller tre, har jeg nu en prototype som er bygget på .Net framework 4.0 (jeg kunne godt have brugt 3.5, men så skulle jeg sende wpftoolkit.dll’en med). Hvis der er nogen der er interesseret i kildekoden, så kontakt mig – den er naturligvis PD (public domain). Og til sidst – en lille teaser:
Screenshot

NHibernate querying – a matter of knowing your scenarios

Skrevet - Saturday, June 26th, 2010 kl. 10:48 | Kategori - * Rants.

These past few days, I’ve held a company-specific course on NHibernate. It went really well, and I believe the participants also got those few golden eggs that makes the course worthwhile for them. They had been using NHibernate for some time and have specialists abroad – so, it was with some trepidation I approached the course material.

I focused on relaying the design decisions in NHibernate and then discussed a lot of do’s and dont’s. I think the key thing to learn when using NHibernate is the power of the ISession. Typically, people are locked into a world where they need to express things as you do with SQL – ie. you query the same way that you would in SQL. Behold the famous Customer vs. Order scenario:

Each Order has a Customer and a Customer can have any number of Orders making the association a one-to-many in the database. But how about querying the database efficiently? Most people will first try this given lazy-loading:

using(var session = GetSession())
using(var tx = session.BeginTransaction())
{

var query = session.CreateQuery(“from Order”);
var orders = query.List<Order>();
foreach(var order in orders)
{

Console.WriteLine(“OrderDate {0} with Customer {1}”, order.Id,order.Customer.AccountNumber);

}

}

This will result in the dreaded Select N+1 where N is the number of Customers that have Orders. Worse, it opens equally many database-connections. (To explain – everytime we hit an Order with a Customer that has not yet been loaded, an SQL query is sent for the Customer – if we hit a Customer that has already been fetched NHibernate will take it from the 1st level cache. Okay, most will then try this:


var query = session.CreateQuery(“select o from Order o join fetch o.Customer”);

We have now reached our goal, right? While it is true that we have reduced the number of queries to one and thus avoided Select N+1, we have a potential problem left. The problem with joins is that we will return a potentially much larger result-set (called the Cartesian product). Suppose our Customers are really heavy on data – and each Customer has many Orders – we will effectively be returning the same heavy customer data object many times over. Let’s say each Customer is 10 KB and each order is 1 KB and each Customer has on average 1.000 orders and there are 10.000 Orders in total. We will now be transferring 1 KB * 10.000 (orders) and 10 KB * 10.000 (customers each returned on average 1000 times) making for 110.000 kb or ~ 107 MB…

How to solve this conundrum – SQL cannot help us here, since it will have exactly the same problem? Well, there is one thing left to exploit. The ISession’s IdentityMap:


session.CreateQuery(“from Customer”).List();
var query = session.CreateQuery(“from Order”);

Why does this work? Every time anything is loaded in an ISession, it is stored in the 1st level cache. This when we iterate over Orders and query for the Customer, it will result in a cache-hit every time. Given our previous example, we have reduced this to two queries, resulting in 1 KB * 10.000 (orders) and 10 KB * 10 (customers) = 10.100 KB ~ 10 MB. Only one thing is still bugging us – we open two connections to the database – but we can get rid of this using MultiQuery:

using(var session = GetSession())
using(var tx = session.BeginTransaction())
{

var multiQuery = session.CreateMultiQuery();
multiQuery.Add(“from Customer”);
multiQuery.Add(“from Order”);
var list = multiQuery.List();
foreach(var order in ((IEnumerable)list[1]).OfType<Order>())
{

Console.WriteLine(“OrderDate {0} with Customer {1}”, order.Id,order.Customer.AccountNumber);

}

}

As with all performance optimizations – this is a contrived example – you will rarely run into such improvements – and you need to know your scenarios to decide which is the better thing to do – basically what are we trying to reduce? The amount of data – the amount of connections and what possibilities do we have. Also, in a real world scenario, you would use NH Profiler or SQL Profiler to determine that it is actually a problem before deciding to performance optimize in the first place. Optimizations come at a price… reduced readability of the code and thus increased maintenance.

Google vs books

Skrevet - Saturday, June 19th, 2010 kl. 22:56 | Kategori - * Rants.

I am reading up on usability at the moment and I passed a usability guru’s website – Jacob Jensen. He has strong opinions – and I like strong opinions and tend to agree with him mostly. Well, that’s up until now – I read an article by him entitled “Google makes you dumber” (link). That one irked me enough to be writing this blog post.

His basic premise is that by making it too easy to obtain information – people will stop being critical about the information and just take the first search result as truth and skip over the in-depth discussion – making us dumber. I read through the comments – and one struck me in particular: “This seems to me a continuation of the eternal “calculators are evil” debate” (Leonid S. Knyshov). I agree whole-heartedly with this one. If you need to calculate the interest of your loan – would you do it by hand? Of course not, you would ask your calculator – but wait, does that make you dumber? No, it makes you more efficient (and less errorprone – remembering long-division when it is 10 years since you were taught it…). For me it’s a matter of perception and reason for doing the calculus. If you are trying to learn calculus – yes, you should spend some time understanding why it is calculated this way – study the proofs – trying it out by hand to see if you understand it fully. If you are ‘just’ a user of math… don’t bother. You should only know enough math to use the calculator correctly.

If I didn’t have Google (or StackOverflow for that matter), I would be a much less efficient programmer. I work in such small teams that we will eventually reach a consensus on what is best practise. We will search for information using our best practise as the basis. Which will in turn lead us to reading books that agree with our best practise. Also, if I had to understand everything about the compiler, performance of List<T> when doing swapping and the internals of representing colors on a TFT screen with backlighting – I would be in an never-stopping loop of trying to stay up-to-date. And if I had to do it by reading books using library indexes to find relevant information… well, you get the picture.

I rely on frameworks, 3rd party condensed API information, blogs, forums, google… and books to give me just enough information to be able to do my job right – which entails doing things efficiently and good enough for the customer to be happy. Will I be rewarded by increasing the performance of my IO-operations by 10% by spending half a year understanding how SSD-disks perform? Probably not. Basically, throw your energy at your core competency – for me this means: “Read everything you can find on design patterns, commanding, templating, styling and nHibernate. The rest… I’ll rely on peers.

So, Google isn’t making me dumber – quite the contrary. Everyone using Google intensively for just one project will know that Google isn’t the answer to everything – and you have to very carefull about who you trust. I once heard a comment about people using Google as a spelling-checker – that you would only find people that were spelling as badly as yourself… You need to know how to search and how to figure out if that site is reliable. So, source criticism is vital – just as it is with books. As for reading in-depth about a particular subject – yes, the author of a book has probably done more research compared to a blog-writer – but a blog-writer will have used the time spent researching doing practical work.

So, trying to conclude… it’s not Google vs. books – it’s a stupid battle – each works differently, but used in unison – they are close to unbeatable… (I use Google to find the right books…) Treat Google as what it is – a great (and fast) indexer. Google will not answer questions you didn’t know you had, books, blog-content etc. might. But Google will let you find that enthusiast that just never got around to writing that book his knowledge entitled him to.

Is this thing on..? *taps microphone*

Skrevet - Sunday, June 13th, 2010 kl. 23:00 | Kategori - * Rants.

Sometimes, I’m wondering whether anyone is actually reading my posts here at GoblinCave. I realize that many will stop by only once or twice when a google search has turned this way – but I have no idea if there is an audience for the posts I’m writing.

So, a quick raise of hands (read: post a comment) – anyone think this site provides actual value, or am I yelling into an empty void?

M-V-VM Building an ERP-system – part 10 of N – OrderLines

Skrevet - Sunday, June 6th, 2010 kl. 22:15 | Kategori - * Coding, English posts.

I’ve saved the goodies for the last post. We are now ready to edit an order after post 9 – and we want to do it in style. We want to present the user with a really nice interface for fast input. We could have done it the old-fashioned way with an ‘Add’ button for adding an orderline in a new window, but hey, we got a shiny ‘new’ DataGrid in 4.0 – so let’s put that for a spin:

public interface IOrderDetailViewModel : IEntityViewModel<IOrder>
{

DateTime OrderDate { get; set; }
ICustomer Customer { get; set; }
ObservableCollection OrderLines { get; }
IAvailableCustomerSelection AvailableCustomers { get; }

}
public interface IOrderLineViewModel : INotifyPropertyChanged
{

IOrderLine CreateUpdatedOrderLine();
decimal Quantity { get; set; }
string Description { get; set; }
decimal PriceEach { get; set; }
decimal TotalPrice { get; }
void SetInvoiceLine(IOrderLine orderLine);

}

Okay – that should provoke a few comments…

You made a typo – shouldn’t the ObservableCollection<OrderLineViewModel> be of <IOrderLineViewModel>?
Actually no. The problem lies with the DataGrid – when there are no items in the collection, it will not show the ‘new item placeholder’ since it does not know whether it is possible to do so. It needs to know which class is to be instantiated and that class must have a default no-argument constructor. And since the ViewModel exists to please the View – there’s nothing for us to do, but satisfy the whims of the View.

But you still made the IOrderLineViewModel interface?
A valid point. It is mostly for consistency – I don’t like it when 99% of a the same type of class has interface and the last 1% doesn’t – it makes me think too much. “Why was it that class didn’t have an interface…” – “Argh, why is there two more classes than interfaces for ViewModels…” – those kinds of questions pop up every once in a while, and they are noise. The interface doesn’t cost me a whole lot of time, but it saves time when I don’t have to wonder why it isn’t there 6 months from now.

Why are there setters on the properties in the IOrderLineViewModel – IOrderLine doesn’t have them?
Remember that the ViewModel isn’t the Model – it’s a View of it. Here the OrderLineViewModel acts as an input-helper for the user. It allows the user to input orderlines without respecting the constructor of OrderLine. Basically, the user can come back to an orderline and change it before committing it to the order. And it gives the semblance to the user that the order line is editable, when it actually is not.

I will not go into further detail of the implementations – I’ve already made 5 more posts than originally planned and 10 is a nice round number. So, what have I tried to show you, the reader? First off, I’ve tried to give you a glimpse of what I do, when I program ERP-systems – second, I’ve shown you how I handle (some of) domain driven design in the UI and finally third – I’ve given a few pointers and ways to handle collections, null and properties that does not exist in the Model. I hope you enjoyed the series – and hope, I’ve shown you a few things that might help you get past a few hurdles using M-V-VM.

About the series:
The solutions introduced here are not entry-level material. You should understand generics and basic patterns to fully utilize the material presented. The solution represents about 3 years of experience working with one ERP-solution. Some of the choices taken are heavily influenced from the large-scale solution and may seem overkill for the simple examples here, but the idea is to show the end-result of my experience and hopefully you as the reader will at least see a new way of doing things. The solution is built in .Net 4.0 with heavy use of WPF’s capabilities. Here you can find the source-code for the series. You are free to use this code for any purpose, but it is presented as-is with no guarantees. Enjoy!

« Previous Page« Forrige indlæg« Previous Page · Next Page »Næste indlæg »Next Page »