It’s All About the Gravy: Making Good Things Better
Question: How can you take an ordinary dish, jazz it up a bit, and make it suitable to fit in a Thanksgiving feast?
Answer: Add sauce.
Even something like mashed potatoes can be made significantly more palatable by adding gravy. Not to say that mashed potatoes are not an enjoyable food on their own, but when that little bit extra is added (whether it’s gravy, cheese sauce, a bit of cream and garlic, or cream cheese and parsley) it suddenly becomes that much better. Software is no different. Allow me to explain.
Let’s take an ordinary application that has a particular feature set: let’s say something that tracks inventory. Let’s say we have a warehouse worker named Jimmy. Jimmy’s boss comes up to him and asks him how many of a particular type of widget they have in stock. Now Jimmy hasn’t been working there too long, so he doesn’t know the widget’s SKU by memory yet. He has to ask Daryl, his co-worker what the SKU is in order to look how many widgets there are. Either that, or he has to go grab a widget off the warehouse shelf, carry it back to his desk (or memorize the SKU) and then look it up. Now on paper, the software’s features would read something like “Allows users to look up existing inventory levels”. But, from the story you just read, there’s definitely some usability missing. It’s not that the core feature is missing – it lacks flavor. It lacks sauce.
Let’s take that same scenario, and that same feature – looking up inventory levels, but with a tweak. Jimmy’s boss comes to him and asks how many of a particular type of widget they have in stock. Jimmy looks at the inventory program, and starts typing in “Widget”. Before he’s done, it’s generated a list of possible types of widgets. He clicks on the right type of widget, and all the related inventory information is pulled up.
Both pieces of software have the same basic feature – looking up inventory levels, but one has the extra “sauce” – features that make it that much more usable. If both pieces of software were sitting in boxes on a shelf, they could both have the same feature listed on the back of the box, but clearly the one piece of software is a much better product.
So how does one find their own “secret sauce” to make a software project that much better? I’ll talk about that in my next blog post.
2011 in review
The WordPress.com stats helper monkeys prepared a 2011 annual report for this blog.
Here’s an excerpt:
The concert hall at the Syndey Opera House holds 2,700 people. This blog was viewed about 15,000 times in 2011. If it were a concert at Sydney Opera House, it would take about 6 sold-out performances for that many people to see it.
.Net Clipboard.SetText and TextDataFormat.Html
Here’s something that I recently discovered. When calling Clipboard.SetText with the TextDataFormat set to Html, I encountered an issue – an exception being thrown because the text being put onto the clipboard was not in the correct format. It turns out there’s a bit more to setting Html text to the clipboard than just setting the TextDataFormat. I came across this post that describes things in more detail.
Recent Trip to Las Vegas
When most people go to Las Vegas, they probably go to see the strip, the bright lights, the casinos. I didn’t go for that. I went for a ride in this:
I have now set my personal fastest record as a passenger in a car – 145 mph. I’m sure it would have gone faster, but the back straight on the track was only so long. That, and I can now say that I have been airborne in a car.
That same car is the one that was used in this video:
I missed the filming of the above video by a day. My original plan was to get down there in time to see them shooting the video as well, but the 20 hour drive to get there took a little longer than expected. Either way, it was still a blast.
DataGridView Performance Tweak
I ran into this one the other day, and figured I’d share it.
A particular dialog seemed quite slow to update a bunch of data. I did a bit of rough profiling using the .Net Stopwatch class, and narrowed it down to a few key areas that were taking quite a long time. The worst culprit of the bunch: adding new rows to a DataGridView. It was taking somewhere in the neighborhood of 11 seconds to refresh a list of several hundred items in a DataGridView.
After doing a bit more digging I narrowed this down a bit further. One thing that was being done is that the row color was being set after the row was added, like this:
dataGrid.Rows.Add(parameter1, parameter2, parameter3);
dataGrid.Rows[dataGrid.Rows.Count - 1].DefaultCellStyle.BackColor = Color.LightGray;
Create a new DataGridViewRow, and add it to the DataGridView, then set it’s color. Seems simple enough, right? It turns out this is definitely the wrong way to do things, even if it first appeared to be the most obvious. A bit of testing later, and I came up with something that looked like this:
DataGridViewRow row = new DataGridViewRow();
row.Cells.Add(new DataGridViewTextBoxCell());
row.Cells.Add(new DataGridViewTextBoxCell());
row.Cells.Add(new DataGridViewTextBoxCell());
row.SetValues(paramter1, parameter2, parameter3);
row.DefaultCellStyle.BackColor = Color.LightGray;
dataGrid.Rows.Add(row);
Doing things this way (creating the new DataGridViewRow, setting it’s color, then adding it to the DataGridView) resulted in a much faster dialog. Much much faster. Rather than the ~11 seconds it was taking before, it was down to ~160 ms.
So, remember kids, if you are wanting to set the row coloring on a DataGridView, do it before you add it to the grid. Setting it afterwards seems to result in redrawing the entire grid which is a lot slower.
(I do realize that using a DataGridView in virtual mode would probably be the better solution, but for the time being, this seems to more than meet the requested needs).
Cool trick with Visual Studio Templates
I’ve recently been playing around with creating a Visual Studio template to create a default set of classes and interfaces for a Model View Controller. Having never done anything with Visual studio templates before (other than use them), I think it turned out quite well. That being said, there was one thing that took a bit of a workaround.
When creating a Model View Controller (or MVC for short), I wanted the following classes/interfaces:
I[Something]View
I[Something]Controller
I[Something]Service
[Something]View (in this case, a Windows form)
[Something]Controller
[Something]Service
… where [something] is the name of the actual MVC you want to create.
The issue that I ran into was in the actual template code. I was using the $safeitemname$ template parameter where I needed it. Unfortunately this didn’t quite work well in the Controller, as the value of the $safeitemname$ being passed into the controller already was “SomethingController”, not just “something”. The workaround for this was to use the $fileinputname$ template parameter instead. In this case the value of $fileinputname$ was just “something”, not “SomethingController”. All the examples out there seem to just show $rootnamespace$ and $safeitemname$. Changing it to the $fileinputname$ worked like a charm.
So, moral of the story: Try using $fileinputname$, not just $safeitemname$.
I’m almost tempted to create one of these for GameScreens in my current code that takes care of game screen management, sort of like the XNA sample. It would make adding a new GameScreen an absolute snap.
Just a collection of parts…
I was chatting with a friend a few days ago about a tech demo that he had created several years ago. It was really quite impressive looking at the time, and he was able to make a short game out of it where you were a pirate and had to collect some treasure.
In talking, he described it as ‘really not much more than a model loader’*. The interesting part about that is that it was mostly true – it really was just a model loader hooked up to a physics engine. At the same time though, he was able to make a game out of it. This brings me to today’s point:
Who cares if it’s a collection of parts? It’s how it plays that really matters.
It doesn’t really matter if you’ve managed to create the latest greatest renderer – if there’s no gameplay to play, people won’t play it. Don’t be afraid to cobble together a collection of parts and make something out of it.
I always find it interesting when people use/abuse technology to make it do things that the creators of it did not originally intend. I can’t wait until someone manages to abuse my simple scripting system or my dialog system and tools or whatever it is I come up with.
*Not his exact words, but a general idea.
How to set the current row on a DataGridView
Now here’s one that I thought I had done before, but came back to bite me in the butt. Here’s the usual situation:
You’ve got a dialog that has a DataGridView. For whatever reason you need to make it go to a particular row in the grid. (For example, you’ve selected something else in a list, and you want to make sure that that particular related record in the grid is visible).
Here’s what you’d probably think of doing:
//where "i" is the index of the row you want to select...
dataGridView.CurrentCell = dataGridView.Rows[i].Cells[0];
Now this works all dandy and fine, until you start editing the contents of some of the rows. Up pops an exception:
Operation is not valid because it results in a reentrant call to the SetCurrentCellAddressCore function.
Hmm, not cool. So, what’s the workaround? Try something like this:
dataGridView.FirstDisplayedScrollingRowIndex = i;
That should make the first visible row in your DataGridView the row that you were wanting to be displayed. Note that it won’t select it, but at least it will be visible. This sort of thing is useful when you want to make a certain row visible, such as a row that has an error.



