“To sleep: perchance to dream…” Laying aside Shakespeare’s morbid meaning, sleep turns out to be fairly important for programmers, and not only because of the perenial lack thereof. Programming, at least at my level, tends to be mostly about the gestalt; something that I gather is the same for musicians. Ask a skilled pianist to concentrate entirely on the mechanics and he’ll be sure to screw it up. Let him forget the details, though, and the result can often seem like nothing less than magic.
I’m no musician, but even so, it’s much the same for me. When I code, I rarely think about the “code.” My head’s always in the architecture, or some larger context, and I’m always five or six steps ahead. More to the point, it would be fair to say that I’m a true “expert,” so it’d be rare for me to encounter a given task that I wouldn’t have a bunch of alternate solutions for. (If this’ all starting to sound a bit like hubris—and I’d hate to admit this—you’d be absolutely right!)
The important thing to realize is that my entire approach usually works for me, just fine. I do the do, and code seems to all but fly. Even so, I would be lying if I told you that “All was always swell in Glocca Morra.” As a rule, I tend to get tripped up by the so-called “simple” stuff; things like syntax mistakes and namespace issues. Even so, I’ve been knocked in the knees—more times than I’d love to avow—by one simple phrase: “I know what I’m doing!”
Case in point, I needed to bind a bunch of enums to a standard WPF ComboBox, last night. The entire thing should have been a cinch, inasmuch as I’ve coded hundreds of combos in my time. What I didn’t realize, though, was that I had never used “Microsoft’s” ComboBox before. Their standard geegaws are OK in their own way, but given my druthers, I generally prefer to use something that’s a bit more advanced, like the excellent ComboBoxEdit by DevExpress, instead. Combo-shombo, they all look alike. Surely, they’d bind the same way; right? Wrong!
Irony and hubris being closely aligned, the reason I was having this problem in the first place was entirely due to my blog. I’m writing a tick-fetch / bar-aggregation robot (called BarFetch; look for it in a week or so). Inasmuch as I thought to share the code, I decided to forego my usual libraries and code closer to the raw metal. Big mistake!
Given a few zzzzz’s, though, the now obvious fact that I didn’t “actually” know what I was doing popped right into my head. Needless to say, as soon as I knew what I didn’t know (echos of Donald Rumsfeld), the problem was 99% solved.
Indeed, a quick bit of Googling brought me to Steve Aube’s Step by Step WPF Data Binding with Comboboxes article on CodeProject.com which gave me an answer straight away. Given Steve’s excelllent article, you might ask why I chose to bother with writing one of my own. We’ll, he did do a decent job, but his solution used too much code, as far as I was concerned. In particular, I didn’t like his approach which relied on an application-wide lookup table to supply a descriptive string for each of the enumeration values. Regardless, he showed me the important thing, that you need to bind the ComboBox.ItemsSource to a collection of objects that have at least two properties; one for the DisplayMemberPath and one for the SelectedValuePath. It won’t matter what sort of struct or class you use, so long as you have those two properties, as show below.
<ComboBox ItemsSource="{Binding SaveTos}" DisplayMemberPath="Description" SelectedValuePath="Enumeration" SelectedValue="{Binding Model.SaveTo}" />
I chose to implement a handy generic ComboItem class since I wanted to use as little custom code as possible. As you’ll see in my (Main)ViewModel, it only takes a single line of code to initialize the SaveTos property:
SaveTos = EnumHelper.ToComboItems<SaveTo>(true);
The rest of the code (excepting the handy helper classes, which you can find in the even more handily named “Helpers” folder) is basic MVVM and initialization stuff, which I trust will be fairly easy to understand.
You can download the complete VS2012 project from here. Before you get started, though, you should probably catch up on those zzzzz’s…