So previously I'd thought writing our own designer for Windows Workflow might be too time consuming, but today I found this lovely little designer which could be the basis for our own designer. It doesn't have any support for adding code to a workflow but I consider that a plus point. I don't actually want our business analysts to even see a code editor. If we can import and export to Visual Studio whilst keeping any code behind intact this may be a marvellous solution. Keep watching...
Thursday, March 15, 2007
Tuesday, March 13, 2007
Loving Windows Workflow, hating Windows Workflow
Thursday, March 08, 2007
Panic Over - Climate Change is a Swindle
I was under the impression that we were all in agreement, that climate change is happening and it's out fault. But according to Channel 4's documentary this evening, we've all been conned. Apparently, although historical rises in CO2 do match rises in temperature, it's the rises in temperrature that drive the rises in CO2 rather than the other way round. I get the feeling that if this were the case, there would be a few more dissenting voices in the scientific community so I won't be going out to buy a mechanical hippo tomorrow. Even if it is true, the fact is fossil fuels will run out one day so we have to find alternatives, and the sooner we start to do that the better.
Sunday, March 04, 2007
Is Peak Oil here?
New template
Wednesday, February 21, 2007
Sorting in a DataGrid
There doesn't seem to be a lot of information around on getting sorting in a WinForms DataGrid to work with custom collections. So I've done the hard work for you and here it is. First I wrote a sorting class, hopefully generic enough to sort pretty much any kind of simple data types (if your collection contains other objects you'll probably need to update this somewhat).
internal class Comparer : IComparer { private PropertyDescriptor sortProperty; private ListSortDirection sortDirection; public Comparer(PropertyDescriptor sortProperty, ListSortDirection sortDirection) { this.sortProperty = sortProperty; this.sortDirection = sortDirection; } #region IComparer Members public int Compare(object x, object y) { Type propType = sortProperty.PropertyType; int sort = 0; if (propType == typeof(string)) sort = string.Compare((string)sortProperty.GetValue(x), (string)sortProperty.GetValue(y)); else if (propType == typeof(DateTime)) sort = DateTime.Compare((DateTime)sortProperty.GetValue(x), (DateTime)sortProperty.GetValue(y)); else if (propType.IsEnum) sort = (int)sortProperty.GetValue(x) - (int)sortProperty.GetValue(y); else if (propType == typeof(int)) sort = (int)sortProperty.GetValue(x) - (int)sortProperty.GetValue(y); else if (propType == typeof(Type)) sort = string.Compare(sortProperty.GetValue(x).ToString(), sortProperty.GetValue(y).ToString()); else if (propType == typeof(bool)) sort = string.Compare(sortProperty.GetValue(x).ToString(), sortProperty.GetValue(y).ToString()); else throw new NotSupportedException(); if (sortDirection == ListSortDirection.Descending) sort = -sort; return sort; } #endregion }
Then I had to implement the IBindingList interface. Actually most of the IBindingList interface is redundant (makes me wonder why it wasn't broken down into a few smaller interfaces, ISortList, ISearchList etc), so here are the bits that are different to the stubs provided by Visual Studio.
void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction) { sortProperty = property; sortDirection = direction; objectList.Sort(new Comparer(sortProperty, sortDirection)); } private PropertyDescriptor sortProperty; PropertyDescriptor IBindingList.SortProperty { get { return sortProperty; } } bool IBindingList.SupportsSorting { get { return true; } } bool IBindingList.IsSorted { get { return (sortProperty != null); } } void IBindingList.RemoveSort() { sortProperty = null; } private ListSortDirection sortDirection; ListSortDirection IBindingList.SortDirection { get { return sortDirection; } }
objectList is my internal ArrayList that contains the collection of objects I'm interested in.
I'm not entirely happy with this solution. I have a lot of collection classes and each one has this same bit of code in it, which always smells a bit bad to me. At some point I might try to create a base class that encapsulates this functionality but it doesn't look too straightforward, since IBindingList requires IList, ICollection and IEnumerable implementations as well...
Tuesday, February 20, 2007
Metastorm Resources
As well as getting hits from people searching for remedies to their medical problems with their bell ends (hint: go and see a doctor), I also get a few hits from people trying to track down information about Metastorm e-Work/BPM. So here's a short list of potentially useful sites.
Process Mapping - OK, it's my employer so I'm biased but it has some useful stuff. If you develop with e-Work be sure to grab a copy of the Procedure Documenter Designer add-in, which not only automatically documents your procedure but also checks for problems in your procedure that are missed by the Designer's validation.
Process Mapping Forums - OK, it's my employer again but if you're looking for an online community to discuss e-Work issues, this is definitely the best place to go. The official Metastorm newsgroups are like a ghost town, the once great eworkdev.org is now a site about Chinese babies and the only other one I'm aware of, eworkhelp.org, seems to be dying due to lack of people and increasing spam.
FreeFlow - Hmm, alright, this is mine... But if you want to integrate .NET and e-Work, these class libraries may well help. There's also a replacement for the abysmal Metastorm admin tools, which I use everyday (can't remember when I actually used the official tools)
BRD - Thought I better add something that hasn't got anything to do with me just to make me look a little bit impartial. BRD produce the Swift client, an alternative web-based client, that provides quite a few features not available in the standard Metastorm client.
If you have any other links, let me know and I'll update this list.
Thursday, February 15, 2007
DataGrid copy to clipboard
Here's some code I knocked together to copy the contents of a WinForms DataGrid to the clipboard. Probably won't work for all possible data sources but it was good enough for my needs.
public void CopyToClipboard() { StringBuilder builder = new StringBuilder(); for (int i = 0; i < ts.GridColumnStyles.Count; i++) { if (i > 0) builder.Append("\t"); builder.Append(ts.GridColumnStyles[i].HeaderText); } builder.Append(Environment.NewLine); CurrencyManager manager = (CurrencyManager)BindingContext[DataSource]; if (DataSource is DataTable) { DataTable dt = (DataTable)DataSource; foreach(DataRowView r in manager.List) { for (int i = 0; i < dt.Columns.Count; i++) { if (i > 0) builder.Append("\t"); builder.Append(r[i].ToString()); } builder.Append(Environment.NewLine); } } else if (DataSource is IList) { for (int i = 0; i < manager.List.Count; i++) { object item = manager.List[i]; Type objectType = item.GetType(); for (int j = 0; j < ts.GridColumnStyles.Count; j++) { string colName = ts.GridColumnStyles[j].MappingName; PropertyInfo propInfo = objectType.GetProperty(colName); object propertyValue = propInfo.GetValue(item, null); if (j > 0) builder.Append("\t"); builder.Append(propertyValue.ToString()); } builder.Append(Environment.NewLine); } } else throw new NotSupportedException(); Clipboard.SetDataObject(builder.ToString(), true); }
Saturday, February 10, 2007
Resizing columns to fit in a DataGrid
I wanted to automatically set the width of columns in a WinForms DataGrid to something sensible based on the contents (using .NET 1.1 for a number of reasons). I've seen the solution to this in a couple of places but they didn't work for me because I'm using a grid that inherits from DataGrid and adds a few helper methods. So here's what I've come up with.
public void AutosizeColumns() { Type t = GetType(); t = t.BaseType; MethodInfo m = t.GetMethod("ColAutoResize", BindingFlags.Instance BindingFlags.NonPublic); for (int i = 0; (i < TableStyles[0].GridColumnStyles.Count); i++) { m.Invoke(this, new object[]{i}); } }
Sunday, February 04, 2007
The CSS media attribute
I was going to write about this some time ago and never got round to it but Jeff Atwood covers it much better than I could ever hope to. Another reason I thought I'd highlight this is after a conversation with one of our clients who'd paid a company to write an ActiveX control to produce printer friendly versions of web pages. There really wasn't any need, it's trivially simple to produce a stylesheet for printer-friendly output, generally all you need to do is hide some of your headers and menus etc. Even with my pathetic CSS skills I managed to create one for the Random Pub Finder.
On the other hand I'm not so sure about the use of a handheld stylesheet though. I did one of these for the Random Pub Finder as well, but as far as I can see we never get any hits from handheld devices. Also, I may be wrong but I think quite a few handheld devices actually ignore the handheld stylesheet and just render websites using the standard stylesheet. This is probably due to the lack of websites that actually provide a handheld stylesheet, meaning any handheld device needs to be able to cope with full-size pages anyway. And finally, it's a right pain testing your site against the huge number of devices out there, particularly as the emulators always seem to be a pain to set up.
Friday, February 02, 2007
Installing a .NET assembly with COM interop
I've written a .NET 1.1 assembly that needs to register for COM interop. I've been using the Visual Studio 2003 installer to build my installer, because it's generally good enough for what I'm doing and it's free. OK, it's not exactly free, but who buys Visual Studio for the installer bits?
Anyway, the installer had been working fine by setting the Register property of the assembly to vsdrpCOM but when I went to test the installer I'd built today after some changes to the assembly it wasn't getting registered. Oddly the install completed and didn't suggest there was a problem but the registry was empty. I could register the assembly using regasm, but that doesn't seem like such a good solution for customers!
So after a not so quick Google later I came across this newsgroup posting (near the bottom) which showed a solution to the problem. And it worked. Problem solved. What I particularly like about this solution is that I'm now back in control of registering my assemblies, rather than being in the hands of the installer's black box implementation, which I've had weird problems with before.
Thursday, February 01, 2007
So what is a bell end?
I noticed that a search for what's a bell end on Google brings up this site at number one, so I thought I better answer the question.
So here goes, bell end refers to the end of a man's, er, manhood. The name came about because it's shaped somewhat like a bell (go on have a quick check, nobody's looking) and it is, in fact, the end. It's a simple as that, although it's often used as something of a derogatory term, where someone might say "he's such a bell end".
The obvious follow on question is why on earth I chose it as my blog name? And the answer to that is I'm not entirely sure. I've certainly been called it quite a few times (due to the surname) and couldn't think of anything more appropriate at the time.
BlogSpot not very well
Lots of people getting a bX-vjhbsj error, as am I. So you probably can't see this...
Wednesday, January 24, 2007
Snow
Tuesday, January 23, 2007
Skype has reached critical mass
Looking at my Skype client running today, I see there are nearly 9 million people logged on as I write this. Some would say that's enough to show Skype has reached critical mass. But for me the real sign that Skype will soon take over the world is this. My mum uses Skype. I don't mean it's installed on her computer and she ignores it. No, she actually called me up on it the other day. And today she started an instant messaging session with me. So congratulations to Skype for writing a piece of software that is simple enough for a pensioner with techno-fear to use. And congratulations on your impending world domination.
Friday, January 19, 2007
Things annoying me today
Empty try-catch blocks - "Oh shit, this bit of code fails, I can't be bothered working out what's going on, I'll just catch the exception (and any other exceptions that are ever thrown) and ignore it. Oh and I won't bother putting a comment in the code to explain why I'm catching this particular exception, cos I don't really know why I am."
Well, I guess the thought process is something like that.
Pointless member variables - OK, so you know what a class is and you know what a member variable is, but that doesn't mean every single variable has to be a member variable. It doesn't make your code more object-oriented, it just makes it more complex. If it's only used in one function, then it probably only needs to be declared in that function. In a managed environment, it means the variable goes out of scope earlier and doesn't have to live for the entire life of the class instance. And your code is more maintainable. Although I'm guessing maintainability wasn't the prime concern of whoever wrote this app...
Wednesday, January 17, 2007
Why you should be using the .NET Framework
Larry Osterman has written a series of posts about software contracts. Well that's what they are meant to be about, but in the end they've been more about the fact that using the PlaySound API asynchronously is really amazingly difficult. One problem is that it's not documented particularly well, but the main problem is the design. The caller allocates some memory, which it must clean up after the sound has finished playing, but if you play it asynchronously you don't get any notification of when it has finished. There's a number of solutions, like kicking off the call synchronously in a separate thread or polling to see when the sound has finished. Larry even went so far as to provide some code to find out how long a WAV file is. Unfortunately some developers 'solve' the problem by just never freeing the memory.
Anyway, this just reminded me of what a complete PITA the Windows API can be, with weird structures and pointers to pointers, and all the docs expecting you to be a C programmer. To be fair, lots of it was designed 15 or more years ago, when PCs were completely different beasts to what they are now but I'm so glad most of my development is now using the .NET Framework. And playing a sound? Actually that was a gaping hole in .NET 1.1 but .NET 2 has the SoundPlayer class. For an async experience, call AsyncLoad, respond to the LoadCompleted event and then call Play and that's it.
Friday, January 12, 2007
IE7 Uptake
According to the IE blog, they reckon 25% of web users are now using IE7. I'm seeing about 20% on my sites, but I bow to their bigger sampling space. Even so, it looks like I was somewhat over-optimistic with my prediction.
Thursday, January 11, 2007
Things annoying me today
FOR XML RAW - Why on earth would you ever use this in a stored procedure? OK, I can think of one use, when you want to do some kind of XSLT on the stored procedure output to produce some HTML or whatever, but not just so you can treat the output from a stored procedure as an XML document. What's the point? Just traverse the record set using the provided database classes.
Commented out code - If you're using a source control system (and if you're not then you're doomed), why leave commented out code lying around? It's all stored away in the file history. If I do a search for a call to a function, finding lots of commented out code is a waste of my time.
Copy and paste code - It's great to fix a bug in some code, then to find it's been reproduced verbatim in 4 other places in the project...
Monday, January 01, 2007
John Naughton's predictions for 2007
I always read John Naughton's column in the Observer, I'm not really sure why. Sometimes he has some valid points but he seems so consumed with hatred for Microsoft that he often completely loses the plot. His predictions for 2007 (towards the bottom of this article) seem to me to be some way off the mark.
First up, we'll see the "continued decline of Microsoft". He's been predicting this for so long, he's bound to get it right at some point. Apparently Vista may be the last version of Windows, er why? There's nothing in the article to back up this theory. Also some customers may have to upgrade their hardware to run it. Nothing new there, that has been the case for every new release of Windows but isn't reason enough for it to fail.
Not only that, "The trauma of producing Vista has shaken Microsoft to the core". Really? Sure, it took longer than expected but then so does every bit of major software. He then goes on to say Microsoft has become a middle-aged company, a point that I do agree with. Of course the bigger question is whether Microsoft can continue to use its huge cash reserves and near monopoly position to overcome that particular problem.
He goes on, "the PC is no longer the cornerstone of our information ecology. The network has become the computer". Hmm, unless I'm mistaken every time I connect to the internet I do it through some kind of computer, I can't mind-meld with Google just yet. And most of those computers still run Microsoft software (about 90% of the ones that hit my sites).
Then he moves on to Google's rise. He says its dominance is "underestimated by the usual market-research statistics, which put Google's market-share in the upper forties". I agree with this point, our logs suggest Google is driving about 70-80% of our search traffic. But as the Internet Outsider points out this is not necessarily a good thing. Google is going to find it hard to increase its market share much more, so where will revenue growth come from, since most of its income is based on search?
Finally he moves onto virtualisation technologies being a big thing in 2007. He correctly points out that server farms use up a hell of a lot of resources but I fail to see how virtualisation is going to help here. Having two virtual servers running on one physical server doesn't double the processing power, since each virtual server will essentially have half the processing power of the real server, in fact slightly less due to the overhead of the virtualisation software. Where virtualisation is useful is for running a piece of software on a different OS. So a Mac can run Windows software or vice-versa. I think this could be very useful to a company like Microsoft, since it can forget about backwards compatibility in its operating system, instead letting incompatible software run in its own virtual machine, which in turn may mean their next OS release will be a little easier to get out of the door.
