Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

Tuesday, August 27, 2019

Loading an image into an ImageButton from an EmbeddedResource

Sad, but this took me awhile to figure out.  A lot of the examples on the web are incorrect so it took quite a bit of thrashing to figure this simple thing out.

The way to load an image into an ImageButton from an EmbeddedResource is to of course add an image to your project and mark it as EmbeddedResource. 

The next step is to determine the “path” to this resource.  If the project name is “Project” and the folder you added your image to is named “Folder” and the image is named “Image.png” then the “path” to this image is "Project.Folder.Image.png”

Then it is a simple process to use the static class ImageSource, like this:

ImageSource.FromResource("Project.Folder.Image.png")

Sunday, August 25, 2019

Back in the (programming) saddle again!

I never thought it could happen to me.  I had publicly said, many times, that it just could never happen to me because it was such an integral part of my life, but it did.

I burnt out on programming.

I was stretched just too thin.  My personal life was falling apart from dealing with my wife’s two year losing battle with cancer.  I worked for, what some people would call, one of the best companies in the world: CSG International.  They allowed me to work first from home and then later from the hospital as I cared for my wife.  They bent over backwards to help me through this most painful of times.  But, in the end I realized that I just could not write code anymore.  I was totally burnt out.  So, I did the only honorable think I could do .. I resigned.

And, in my personal life, I was completely drained. After my wife passed, I just needed to escape.  so I did.

To the Philippines.  I have now remarried to a beautiful Filipina and I now have a … DAUGHTER!

When I moved, my sister said that I would be back at the keyboard pounding out code in no time.  Knowing how much programming meant to me, she predicted it would only take two months.

Eighteen months later …

I am finally getting the itch to program again and I have started to learn how to write mobile apps using the Xamarin platform.  I have already hit some snags that were not the easiest to unravel so I figured I would share my journey with the world.

Programming, I missed you!  Welcome back!



Wednesday, August 24, 2016

How do you recognise good programmers if you’re a business guy?


[ Disclaimer: Many years ago I found an article out on the interwebs that described how to recognize a good programmer for the viewpoint of a non-programmer.  Later, in 2012, I wanted to reference it in a blog post and during my search I ran across [this] post where the commenter compared programming to diesel mechanics and then tried to show that the “bad” programmer was the one that *HE* would hire. I wrote [this] blog post with my take on his comparison. 

Unfortunately the original article is no longer available so I am posting a copy of it here so that the original authors wisdom will not be lost.

Remember, I did NOT write this.]

It’s not as easy as it sounds. CV experience is only of limited use here, because great programmers don’t always have the “official” experience to demonstrate that they’re great. In fact, a lot of that CV experience can be misleading. Yet there are a number of subtle cues that you can get, even from the CV, to figure out whether someone’s a great programmer.

I consider myself to be a pretty good programmer. At the same time, I’ve spent a fair amount of time on the business side of the fence, filtering technical CVs for projects, interviewing people, etc. Thanks to this, I think I have a bit of experience in recognising good programmers, and I want to share it in this article, in the hope that it may help other “business guys” to recognise good programmers. And, who knows, perhaps some programmers who have the potential to be good but haven’t really exploited this can also read this and realise what they need to do to become good (although, as I’ll argue, that’s definitely not accessible to all programmers!).

In his article The 18 mistakes that kill startups, Paul Graham makes the following point:

“… what killed most of the startups in the e-commerce business back in the 90s, it was bad programmers. A lot of those companies were started by business guys who thought the way startups worked was that you had some clever idea and then hired programmers to implement it. That’s actually much harder than it sounds—almost impossibly hard in fact—because business guys can’t tell which are the good programmers. They don’t even get a shot at the best ones, because no one really good wants a job implementing the vision of a business guy.

In practice what happens is that the business guys choose people they think are good programmers (it says here on his resume that he’s a Microsoft Certified Developer) but who aren’t. Then they’re mystified to find that their startup lumbers along like a World War II bomber while their competitors scream past like jet fighters. This kind of startup is in the same position as a big company, but without the advantages.

So how do you pick good programmers if you’re not a programmer? I don’t think there’s an answer. I was about to say you’d have to find a good programmer to help you hire people. But if you can’t recognize good programmers, how would you even do that?”

I disagree with Mr. Graham on this one. I think there are a number of very strong indicators of a “good programmer” (and, conversely, strong indicators of a “not-so-good programmer”) that even a business guy can recognise. I’ll summarise some key indicators and counter-indicators in a list at the end of the article.

#1 : Passion

In my corporate experience, I met a kind of technical guy I’d never met before: the career programmer. This is a person who’s doing IT because they think it’s a good career. They don’t do any programming in their spare time. They’re shocked when they find out I have a LAN and 3 computers at home. They just do it at work. They don’t learn new stuff unless sent on a training program (or motivated by the need to get a job that requires that technology). They do “programming” as a day job. They don’t really want to talk about it outside of work. When they do, they talk with a distinctive lack of enthusiasm. Basically, they lack passion.

I believe that good developers are always passionate about programming. Good developers would do some programming even if they weren’t being paid for it. Good programmers will have a tendency to talk your ear off about some technical detail of what they’re working on (but while clearly believing, sincerely, that what they’re talking about is really worth talking about). Some people might see that as maladapted social skills (which it is), but if you want to recognise a good developer, this passion for what they’re doing at the expense of social smoothness is a very strong indicator. Can you get this guy to excitedly chat up a technology that he’s using, for a whole half hour, without losing steam? Then you might be onto a winner.

#2 : Self-teaching and love of learning

Programming is the ultimate moving target. Not a year goes by without some new technology robbing an old, established standard blind and changing half the development universe. This is not to say that all good programmers pick up these changes and ride the bleeding edge. However, there’s a class of programmers that will never, ever pick up a new technology unless forced to, because they don’t like learning new stuff. These programmers will typically have learnt programming at university, and expect to get by on whatever skills they picked up there, plus whatever courses their company is willing to send them on.

If you’re thinking of hiring someone as a programmer, and he ever utters the words “I can work with that, just send me on a training course for a week and I’ll be good at it”, don’t hire that guy. A good programmer doesn’t need a training course to learn a new technology. In fact, the great programmer will be the one talking your ear off about a new technology that you haven’t even heard of, explaining to you why you must use it in your business, even if none of your staff knows how to use it. Even if it’s a technology he doesn’t know how to use yet.

#3 : Intelligence

Some business people assume that lack of social tact and lack of intelligence are the same. Actually, intelligence has several facets, and emotional/social intelligence is only one of them. Good programmers aren’t dumb. Ever. In fact, good programmers are usually amongst the smartest people you know. Many of them will actually have pretty good social skills too. The cliché of the programmer who’s incapable of having a conversation is just that - a cliché. I’ve been to a few meetings of the London Ruby User Group and I can say that with only a very few exceptions, most people there are smart, talkative, sociable, have varied interests, etc. You wouldn’t look at them chattering away in the pub and think “what a bunch of geeks!” - at least until you approach a group and realise they’re talking about the best way to design a RESTful application with a heavy UI frontend.

This doesn’t mean that they’ll all feel comfortable in every social context. But it does mean that if the context is comfortable and non-threatening enough, you’ll be able to have as great a conversation with them as you would with the most “socially enabled” people (perhaps better, since most good programmers I know like their conversation to revolve around actually useful topics, rather than just inane banter).

Don’t ever hire a dumb person thinking they’re a good developer. They’re not. If you can’t have a great conversation with them in a relaxed social context, they’re very likely not a good programmer. On the other hand, anyone who’s clearly very smart at the very least has a strong potential to be a good or great programmer.

#4 : Hidden experience

This is correlated with the “Passion” point, but it is such a strong indicator that I’d like to emphasise it with its own point.

I started programming when I was about 9, on a Commodore 64. I then migrated onto the PC, did some Pascal. When I was 14 I wrote a raycasting engine in C and Assembler, spent a large amount of time playing with cool graphic effects that you could get your computer to do by messing directly with the video card. This was what I call my “cocoon stage”. When I entered that stage, I was a mediocre programmer, and lacked the confidence to do anything really complicated. When I finished it, I had gained that confidence. I knew that I could code pretty much anything so long as I put my mind to it.

Has that ever appeared on my CV? Nope.

I strongly believe that most good programmers will have a hidden iceberg or two like this that doesn’t appear on their CV or profile. Something they think isn’t really relevant, because it’s not “proper experience”, but which actually represents an awesome accomplishment. A good question to ask a potential “good programmer” in an interview would be “can you tell me about a personal project - even or especially one that’s completely irrelevant - that you did in your spare time, and that’s not on your CV?” If they can’t (unless their CV is 20 pages long), they’re probably not a good programmer. Even a programmer with an exhaustive CV will have some significant projects that are missing from there.

#5 : Variety of technologies

This one’s pretty simple. Because of the love of learning and toying with new technologies that comes with the package of being a “good programmer”, it’s inevitable that any “good programmer” over the age of 22 will be fluent in a dozen different technologies. They can’t help it. Learning a new technology is one of the most fun things a programmer with any passion can do. So they’ll do it all the time, and accumulate a portfolio of things they’ve “played around with”. They may not be experts at all of them, but all decent programmers will be fluent in a large inventory of unrelated technologies.

That “unrelated” bit is the subtle twist. Every half-decent java programmer will be able to list a set of technologies like “Java, J2EE, Ant, XML, SQL, Hibernate, Spring, Struts, EJB, Shell scripting”, etc.. But those are all part of the same technology stack, all directly related to each other. This is possibly hard to recognise for non-programmers, but it is possible to tell whether their technology stack is varied by talking to them about it, and asking them how the different technologies they know relate to each other. Over-specialisation in a single technology stack is an indicator of a not-so-good programmer.

Finally, if some of those technologies are at the bleeding edge, that’s a good positive indicator. For instance, today (November 2007), knowledge of Merb, Flex, RSpec, HAML, UJS, and many others… Please note that these are fairly closely related technologies, so in a couple of years, someone who knows all these will be equivalent to someone familiar with the Java stack listed in the previous paragraph.

Update: As a clarification to this point, there’s in fact two indicators here: variety and bleeding edge. Those are separate indicators. A good variety of technologies across a period of time is a positive indicator, whether or not the technologies are bleeding edge. And bleeding edge technologies are a positive indicator, whether or not there’s a variety of them.

#6 : Formal qualifications

This is more a of non-indicator than a counter-indicator. The key point to outline here is that formal qualifications don’t mean squat when you’re trying to recognise a good programmer. Many good programmers will have a degree in Computer Science. Many won’t. Certifications, like MCSE or SCJP or the like, don’t mean anything either. These are designed to be accessible and desirable to all. The only thing they indicate is a certain level of knowledge of a technology. They’re safeguards that allow technology recruitment people in large corporations to know “ok, this guy knows java, he’s got a certification to prove it” without having to interview them.

If you’re hiring for a small business, or you need really smart developers for a crack team that will implement agile development in your enterprise, you should disregard most formal qualifications as noise. They really don’t tell you very much about whether the programmer is good. Similarly, disregard age. Some programmers are awesome at 18. Others are awesome at 40. You can’t base your decisions about programmer quality on age (though you might decide to hire people around a certain age to have a better fit in the company; please do note that age discrimination is illegal in most countries!).

As a final note to this, in my experience most average or poor programmers start programming at university, for their Computer Science course. Most good programmers started programming long before, and the degree was just a natural continuation of their hobby. If your potential programmer didn’t do any programming before university, and all his experience starts when she got her first job, she’s probably not a good programmer.

Disclaimer

None of the indicators above or below are sure-fire indicators. You will find great programmers who break some of those moulds. However, my view is, you’ll rarely find a great programmer that breaks all of them. Similarly, you may find poor programmers that meet (or appear to meet) some of these criteria. But I do strongly believe that the more of these criteria a programmer meets, the more likely they are to be one of those elusive “good programmers” that, as a business guy, you need to partner with.

The criteria in bullets

So, in summary, here are some indicators and counter-indicators that should help you recognise a good programmer.

Positive indicators:

  •     Passionate about technology
  •     Programs as a hobby
  •     Will talk your ear off on a technical subject if encouraged
  •     Significant (and often numerous) personal side-projects over the years
  •     Learns new technologies on his/her own
  •     Opinionated about which technologies are better for various usages
  •     Very uncomfortable about the idea of working with a technology he "doesn't believe to be right”
  •     Clearly smart, can have great conversations on a variety of topics
  •     Started programming long before university/work
  •     Has some hidden “icebergs”, large personal projects under the CV radar
  •     Knowledge of a large variety of unrelated technologies (may not be on CV)
  • Negative indicators:
  •     Programming is a day job
  •     Don’t really want to “talk shop”, even when encouraged to
  •     Learns new technologies in company-sponsored courses
  •     Happy to work with whatever technology you’ve picked, “all technologies are good"
  •     Doesn’t seem too smart
  •     Started programming at university
  •     All programming experience is on the CV
  •     Focused mainly on one or two technology stacks (e.g. everything to do with developing a java application), with no experience outside of it

I hope these help. Let me know below if you have any comments, or anything to add to them!

Thanks for reading.

Friday, November 15, 2013

Creating XAML hexagons without using a PATH element

I was recently working on a small Windows Phone 8 app that needed some tessellated (tiled) hexagons and after searching the web for a simple solution, I did not find what I wanted. 

All of the solutions involved drawing the hexagon using drawing primitives such as the PATH element.  I wanted a “simpler” solution.  I wanted a Grid based solution, and here it is.

To start with I needed to know two semi-basic points about hexagons: what is the ratio of height to width, and (with the hex “standing” on one of its flat sides) what is the the ratio between the horizontal length of the flat and the horizontal distance from the end of the flat side to the edge of the hexagon.  (Boy that is harder to write than it is to just see it)

I found both pieces of information at: Hexnet

Hexnet shows that if the length of one side of a hex has a length of 1, then the overall width is 2 and the height of the hexagon is √3 (approx. 1.73).  So, if we were to build this in a grid, we would have a single hexagon take up 6 cells (2 rows and 3 columns) and our two critical semi-basic points are: √3 to 2 and 1 to .5.

If we wanted a hexagon with an overall width of 200px (200 times our example above), our grid would be defined as:

   1:  <Grid x:Name="LayoutRoot" Background="White" Width="200" Height="173">
   2:      <Grid.ColumnDefinitions>
   3:          <ColumnDefinition Width="*"></ColumnDefinition>
   4:          <ColumnDefinition Width="2*"></ColumnDefinition>
   5:          <ColumnDefinition Width="*"></ColumnDefinition>
   6:      </Grid.ColumnDefinitions>
   7:      <Grid.RowDefinitions>
   8:          <RowDefinition></RowDefinition>
   9:          <RowDefinition></RowDefinition>
  10:      </Grid.RowDefinitions>
  11:  </Grid>



if you look at this grid with gridlines on, you get:


image



Now from here we can either create a outline of a hexagon using 6 line objects, create a solid hexagon using 3 rectangle objects or combine both for an outlined solid color hexagon.


“Wait!”, you say.  “I can see the six lines making up the outline of a hexagon, but how could you do a solid color hexagon with three squares?”


Well, I’m glad you asked.  If you fill the center column with a rectangle, that’s one.  If you make a copy but rotate it 60 degrees using the center as the pivot point and make a third and rotate it –60 degrees then you have your solid color hexagon.


And, if you just start repeating the second and third columns when you add columns, you can start to create a grid full of tessellated (tiled) hexagons, just like I did in this image.


image


And here is the complete xaml I used to create the above image (From this code it was simple to extract rules that I used to create large fields of tessellated (tiled) hexagons in code):


   1:  <UserControl x:Class="Hexagon.MainPage"
   2:      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   5:      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   6:      mc:Ignorable="d"
   7:      d:DesignHeight="346" d:DesignWidth="500">
   8:      <Viewbox Stretch="Uniform">
   9:          <Grid x:Name="LayoutRoot" Background="White" Width="500" Height="346" Margin="50">
  10:              <Grid.ColumnDefinitions>
  11:                  <ColumnDefinition Width="*"></ColumnDefinition>
  12:                  <ColumnDefinition Width="2*"></ColumnDefinition>
  13:                  <ColumnDefinition Width="*"></ColumnDefinition>
  14:                  <ColumnDefinition Width="2*"></ColumnDefinition>
  15:                  <ColumnDefinition Width="*"></ColumnDefinition>
  16:                  <ColumnDefinition Width="2*"></ColumnDefinition>
  17:                  <ColumnDefinition Width="*"></ColumnDefinition>
  18:              </Grid.ColumnDefinitions>
  19:              <Grid.RowDefinitions>
  20:                  <RowDefinition></RowDefinition>
  21:                  <RowDefinition></RowDefinition>
  22:                  <RowDefinition></RowDefinition>
  23:                  <RowDefinition></RowDefinition>
  24:              </Grid.RowDefinitions>
  25:              <Rectangle Fill="Pink" RenderTransformOrigin="0.5, 0.5" Grid.Column="1" Grid.RowSpan="2"></Rectangle>
  26:              <Rectangle Fill="Pink" RenderTransformOrigin="0.5, 0.5" Grid.Column="1" Grid.RowSpan="2">
  27:                  <Rectangle.RenderTransform>
  28:                      <RotateTransform Angle="-60" />
  29:                  </Rectangle.RenderTransform>
  30:              </Rectangle>
  31:              <Rectangle Fill="Pink" RenderTransformOrigin="0.5, 0.5" Grid.Column="1" Grid.RowSpan="2">
  32:                  <Rectangle.RenderTransform>
  33:                      <RotateTransform Angle="60" />
  34:                  </Rectangle.RenderTransform>
  35:              </Rectangle>
  36:              <Rectangle Fill="Aquamarine" RenderTransformOrigin="0.5, 0.5" Grid.Column="3" Grid.Row="1" Grid.RowSpan="2"></Rectangle>
  37:              <Rectangle Fill="Aquamarine" RenderTransformOrigin="0.5, 0.5" Grid.Column="3" Grid.Row="1" Grid.RowSpan="2">
  38:                  <Rectangle.RenderTransform>
  39:                      <RotateTransform Angle="-60" />
  40:                  </Rectangle.RenderTransform>
  41:              </Rectangle>
  42:              <Rectangle Fill="Aquamarine" RenderTransformOrigin="0.5, 0.5" Grid.Column="3" Grid.Row="1" Grid.RowSpan="2">
  43:                  <Rectangle.RenderTransform>
  44:                      <RotateTransform Angle="60" />
  45:                  </Rectangle.RenderTransform>
  46:              </Rectangle>
  47:              <Rectangle Fill="LightBlue" RenderTransformOrigin="0.5, 0.5" Grid.Column="5" Grid.Row="2" Grid.RowSpan="2"></Rectangle>
  48:              <Rectangle Fill="LightBlue" RenderTransformOrigin="0.5, 0.5" Grid.Column="5" Grid.Row="2" Grid.RowSpan="2">
  49:                  <Rectangle.RenderTransform>
  50:                      <RotateTransform Angle="-60" />
  51:                  </Rectangle.RenderTransform>
  52:              </Rectangle>
  53:              <Rectangle Fill="LightBlue" RenderTransformOrigin="0.5, 0.5" Grid.Column="5" Grid.Row="2" Grid.RowSpan="2">
  54:                  <Rectangle.RenderTransform>
  55:                      <RotateTransform Angle="60" />
  56:                  </Rectangle.RenderTransform>
  57:              </Rectangle>
  58:              <Rectangle Fill="LemonChiffon" RenderTransformOrigin="0.5, 0.5" Grid.Column="1" Grid.Row="2" Grid.RowSpan="2"></Rectangle>
  59:              <Rectangle Fill="LemonChiffon" RenderTransformOrigin="0.5, 0.5" Grid.Column="1" Grid.Row="2" Grid.RowSpan="2">
  60:                  <Rectangle.RenderTransform>
  61:                      <RotateTransform Angle="-60" />
  62:                  </Rectangle.RenderTransform>
  63:              </Rectangle>
  64:              <Rectangle Fill="LemonChiffon" RenderTransformOrigin="0.5, 0.5" Grid.Column="1" Grid.Row="2" Grid.RowSpan="2">
  65:                  <Rectangle.RenderTransform>
  66:                      <RotateTransform Angle="60" />
  67:                  </Rectangle.RenderTransform>
  68:              </Rectangle>
  69:              <Rectangle Fill="Thistle" RenderTransformOrigin="0.5, 0.5" Grid.Column="5" Grid.Row="0" Grid.RowSpan="2"></Rectangle>
  70:              <Rectangle Fill="Thistle" RenderTransformOrigin="0.5, 0.5" Grid.Column="5" Grid.Row="0" Grid.RowSpan="2">
  71:                  <Rectangle.RenderTransform>
  72:                      <RotateTransform Angle="-60" />
  73:                  </Rectangle.RenderTransform>
  74:              </Rectangle>
  75:              <Rectangle Fill="Thistle" RenderTransformOrigin="0.5, 0.5" Grid.Column="5" Grid.Row="0" Grid.RowSpan="2">
  76:                  <Rectangle.RenderTransform>
  77:                      <RotateTransform Angle="60" />
  78:                  </Rectangle.RenderTransform>
  79:              </Rectangle>
  80:              <Line Grid.Column="0" Grid.Row="0" X1="1" Y1="0" X2="0" Y2="1" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  81:              <Line Grid.Column="1" Grid.Row="0" X1="1" Y1="0" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" VerticalAlignment="Top" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  82:              <Line Grid.Column="2" Grid.Row="0" X1="1" Y1="1" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  83:              <Line Grid.Column="0" Grid.Row="1" X1="1" Y1="1" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  84:              <Line Grid.Column="1" Grid.Row="1" X1="1" Y1="0" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" VerticalAlignment="Bottom" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  85:              <Line Grid.Column="2" Grid.Row="1" X1="1" Y1="0" X2="0" Y2="1" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  86:              <Line Grid.Column="3" Grid.Row="1" X1="1" Y1="0" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" VerticalAlignment="Top" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  87:              <Line Grid.Column="4" Grid.Row="0" X1="1" Y1="0" X2="0" Y2="1" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  88:              <Line Grid.Column="5" Grid.Row="0" X1="1" Y1="0" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" VerticalAlignment="Top" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  89:              <Line Grid.Column="6" Grid.Row="0" X1="1" Y1="1" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  90:              <Line Grid.Column="4" Grid.Row="1" X1="1" Y1="1" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  91:              <Line Grid.Column="5" Grid.Row="1" X1="1" Y1="0" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" VerticalAlignment="Bottom" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  92:              <Line Grid.Column="6" Grid.Row="1" X1="1" Y1="0" X2="0" Y2="1" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  93:              <Line Grid.Column="0" Grid.Row="2" X1="1" Y1="0" X2="0" Y2="1" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  94:              <Line Grid.Column="2" Grid.Row="2" X1="1" Y1="1" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  95:              <Line Grid.Column="0" Grid.Row="3" X1="1" Y1="1" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  96:              <Line Grid.Column="1" Grid.Row="3" X1="1" Y1="0" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" VerticalAlignment="Bottom" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  97:              <Line Grid.Column="2" Grid.Row="3" X1="1" Y1="0" X2="0" Y2="1" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  98:              <Line Grid.Column="3" Grid.Row="3" X1="1" Y1="0" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" VerticalAlignment="Top" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  99:              <Line Grid.Column="4" Grid.Row="2" X1="1" Y1="0" X2="0" Y2="1" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
 100:              <Line Grid.Column="6" Grid.Row="2" X1="1" Y1="1" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
 101:              <Line Grid.Column="4" Grid.Row="3" X1="1" Y1="1" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
 102:              <Line Grid.Column="5" Grid.Row="3" X1="1" Y1="0" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" VerticalAlignment="Bottom" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
 103:              <Line Grid.Column="6" Grid.Row="3" X1="1" Y1="0" X2="0" Y2="1" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
 104:          </Grid>
 105:      </Viewbox>
 106:  </UserControl>

Thursday, February 23, 2012

I’m a 5.8 out of 6 programmer

If you go to How to recongnise a good programmer, you will see one man’s idea of how to spot a good programmer.  When looking around the web, I stumbled upon this conversation about it.  The last post tried to adapt this to diesel mechanics.  I’ve added my comments in red to the post, since I think the poster does not have a clue what a programmer does.  Maybe I can enlighten him a bit. (I’ve also colored his adaptation in blue.
Let's see how it applies to my business model.
I have a fleet of eighteen wheelers and I need to hire a bunch of mechanics to service Volvo, Kenworth and Mack trucks.

Wow, to compare mechanics to programmers in the first place ... this guy hasn't a clue what a programmer does.  But, just to play along lets see how this works out
The article gives me two possible hiring scenarios which I've adapted to my business.
Positive indicators:
Passionate about technology
Heard about the latest F1 regenerative energy systems.
No, how about more like "Really likes to work on Trucks"?
 
Programs as a hobby
Tinkers with his own dirt bike.
<Sigh> I can see he just does not get it.  More like: Loves to work on Trucks so will do it on his/her own time. 
Will talk your ear off on a technical subject if encouraged
NASCAR galore.
 If you think NASCAR is a technical subject in you field then you will quickly be out of business.
  
Significant (and often numerous) personal side-projects over the years
Remember his Radio-Flyer cart !Amazing how poorly you build your straw man!  If I applied this to mechanics, I would say "Has always had grease under his fingernails." or maybe "Has rebuilt many different Trucks starting in High school"
  
Learns new technologies on his/her own
Reads "Popular Mechanics" magazine. WTF! You really believe you can learn new technologies in "Popular Mechanics"?  There is no way you can run a successful company ... Ok, I'll continue to play along.  If I applied this to Truck mechanics, I would say "Keeps himself trained on the latest engine designs.  Learns about all popular engine modifications."
Opinionated about which technologies are better for various usages
He's keen on Brembo brakes.
OK, I'll assume you know the difference between technologies and products, right?  This is where some of your analogy starts to break down. When was there a major new development in internal combustion engine design?  Basic diesel technology is how old?
Very uncomfortable about the idea of working with a technology he doesn't believe to be “right”
Hates the old carburetor thing.
So you think that a great diesel mechanic would love to get a job with you working on your "Water and Chicken poop powered" Trucks?
 
Clearly smart, can have great conversations on a variety of topics
iTune, iPhone, Roberta Black, Iraq etc.
Another place that this analogy breaks down.  <Sigh> I'll just keep quiet on this one.
 
Started programming long before university/work
As a teenager repaired the toaster and changed the kitchen faucet.More like, knew what a torque wrench was before he started his first mechanics class.  
Has some hidden “icebergs”, large personal projects under the CV radar
Wants to tinker with a jet ski watercraft. Close, more like, knows how to alter a jet ski engine to get a 50% power boost without damaging the engine.
 
Knowledge of a large variety of unrelated technologies (may not be on CV)
Knows the difference between a CD, a regular DVD and a blue-ray DVD.If you are not being deliberately stupid, then <sigh> I’ll just keep quiet.
Negative indicators:
Programming is a day job
Does truck service & repairs for a living.
More like "Never turns a wrench unless he is paid to, and even then he bitched about it.  Why does he do it - its a paycheck."
  
Don’t really want to “talk shop”, even when encouraged to
Prefers to check the service manuals and do the job at hand.
Here you have is completely backward.  This is a prime example of "Learns new technologies on his/her own" above.  Instead, the correct example would be, "Never wants to learn the tips and tricks of other experts, but would rather scratch his ass and complain about the pay"
 
Learns new technologies in company-sponsored courses
If I am going to send him to a GM training course he will gladly obliged.
Nope, more like "Hey Bob, we are going to expand and start working on FIAT's.  The Community College is offering night courses." and Bob replies, "Screw you boss, if you want me to go, it's during work hours, your paying and I'm not going to make up the time."
 
Happy to work with whatever technology you’ve picked, “all technologies are good”
If we decide to buy GM trucks he will gladly work on them
GM trucks? No more like now your going to work on HVAC systems and by-god they had better be as good at is as they were at diesels. 
Doesn’t seem too smart
He does not seem interested in iTune, iPhone, Roberta Black, Iraq etc.
Another place that this analogy breaks down.  <Sigh> I'll just keep quiet on this one.
  
Started programming at university
Learned how trucks are built, how to service them and had hands on practical experience under the supervision of master mechanics in an accredited school with his major in Volvo engine and control module diagnostic and repair and minor in Kenworth engine and transmission repair and has a "specialist" certification.
Another place that this analogy breaks down, but I'll give it a try.  First time the future mechanic ever heard of a ratchet wrench when he got the list of required tools for his new degree. If we were to equate a CS degree to a tech degree and certification, it the tech degree and certification would guarantee that the student has shown that he knows exactly what each tool is, how it is used and if necessary, how to make one from scratch. 
All programming experience is on the CV
Left out his alma-mater racing club where he is the chief mechanic.
<sigh>
 
Focused mainly on one or two technology stacks (e.g. everything to do with developing a java application), with no experience outside of it
He is focused on Volvo and Kenworth and has really no experience with Tatra, Zim, Hino, FIAT and other trucks.
Almost right, if the other types of trucks used different types of engines built with different materials and you needed a completely different set of tools that the mechanic would have no idea how to use.
I don't know why, but I would hire the guy/gal with the negative indicators. Lucian
Well, Lucian, what your saying is that you would rather have a person that only learned what a wrench is after he started school, only does the work because he is getting a paycheck, doesn't even like talking about what he does, refuses to learn anything unless he is paid to do it and thinks that he is equally skilled at working on HVAC as he is on a diesel engine because "All technologies are good"?
Wow, I give your company 6 to 8 weeks before either the "mechanics" you hire starts your building on fire, or you are sued out of business because a "mechanic" put Mack parts on a Kenworth. (remember, all technology is good, right?)
This is why comparing a mechanic (a job where there is always only one way that things go together) and a programmer (a job where there are literally a million ways to do things.  Most of them the wrong way, but quite a few almost correct if not equally correct.)
When every Trucking company builds there own engines, changes the type of engine every couple of years, fixing the engine can be done 1000 different ways, and require the mechanics to use a whole different set of tools for each new type, then we can START to compare diesel truck mechanics to programmers.

Thursday, July 7, 2011

Viewing the contents of a binary file in Visual Studio

The toolset included in Visual Studio is just massive.  I swear that I could use Visual Studio for a lifetime and I still would not have plumbed all its depths.

With that thought in mind, I just realized that I need not look for poor third party applications to look inside a binary file.  I can use my trusty IDE Swiss Army knife, Visual Studio.

There are two ways to view and edit a binary file in Visual Studio:

  1. Simply open a file with the extension of .BIN
  2. After selecting the file in “Open –> FIle…” but before you click the “Open” button, instead click on the dropdown arrow on the “Open” button and select “Open With …”.  Then select “Binary Editor” from the list.

Either way you are then presented with the standard type of Binary File editor (3 columns, 1- The Offset, 2- The binary data & 3- The ASCII representation of the binary data).

In this editor, you can copy, paste, add, alter and delete bytes!

If only I had known this years ago!

Saturday, April 16, 2011

Calculating the average of two angles (two bearings actually)

I recently needed to find the average of two angles.  I was programmatically creating a irregular polygon. I wanted to draw a small square at the points of the polygon, and I wanted the squares to be rotated to the average of the two lines that met at that point.

The issue is that if you have two bearings, one at 20° and one at 350°, or one at 15° and one at 315°. If you just average the two numbers, you get 185°, but the more appropriate number is 5°.  This is called by some a “Wraparound issue” and if you search the web you will see lots of ways to solve this problem. Unfortunately they mostly try to solve it using a mathematical equation.  Now for people that have read this blog for awhile know that I am not allergic to math, but if we can solve this problem simply with an algorithm, we should … that’s what computers are for, right?

So, here is my algorithm and the thought behind it.


(Assumptions: 0 >= bearings < 360)

First if you look at the difference between the two bearings, you will see that there are two possibilities, the actual difference is greater than 180° or less than 180°.  Since we are only concerned about “fixing” the issue when the difference is greater than 180°, that is the first thing we will check.

We will call the smaller value bearing bearingA and the larger value bearing bearingB.

Since we know that bearingB has a larger value and that the difference is greater than 180, so bearingB > 180.

So, if we subtract 360  –  bearingB, then just add bearingA + bearingB and divide the total in half, we are 90% there.

One last check. If the result is less than 0, we need to add 360 back in.





So, example #1
20° & 350°
350 – 20 > 180
350 – 360 = –10
(–10 + 20) / 2 = 5
5 ≥ 0
= 5 °

So, example #2

15° & 315°
315 – 15 > 180
315 – 360 = –45
(-45 + 15) / 2 = –30
–30 < 0–30 + 360 = 354°



And here is the code:



Code Snippet
  1. private static double GetAverageBearing(double bearingA, double bearingB)
  2.         {
  3.             if (bearingA > bearingB)
  4.             {

  5.                 var temp = bearingA;
  6.                 bearingA = bearingB;

  7.                 bearingB = temp;
  8.             }
  9.  
  10.             if (bearingB - bearingA > 180) bearingB -= 360;
  11.  
  12.             var finalBearing = (bearingB + bearingA)/2;
  13.  
  14.             if (finalBearing < 0) finalBearing += 360;
  15.             
  16.             return finalBearing;
  17.         }

Saturday, April 9, 2011

Scripting C++/cli with IronPython (Visual Studio 2008 & IronPython 2.6.1)

Even though there has been a lot of talk about IronPython, there has been very little info about how to use it with C++/cli.  I’ve actually found posts claiming that it is not possible to use IronPython with C++/cli.

Well, it is possible and easy, once you have a working example.  If, not then … well, lets just hope your hair will grow back.

Ok, I’m never one to take the easy way out, but I started by creating a C# dll that called my IronPython script and then called the C# dll from C++/cli.  That worked but seemed overly complicated.  If you do not mind a middleman then I guess it is ok, but if you want to go straight from C++/cli to IronPython, read on.

When I first tried to write a call to an IronPython script from  C++/cli, I tried a direct conversion of C# code into C++/cli code.  That didn’t work, so I then tried using RedGate’s .Net Reflector and the C++/cli add-in for .Net Reflector.  This got me 70% there.  Combining both with some trial and error got me the rest of the way. 

Funny, but when you look at the code, it seems so simple – yet getting there was not easy.

So, the following snippet shows a simple usage of IronPython as a scripting language.  It takes the first parameter passed in prints it to the console, passes it to the IronPython script: ipyStrings.ipy, then prints to the console the value of the same parameter that was passed back.  The IronPython code takes the string, prints it, reverses it, then sends it back.

C++/cli code:

Code Snippet
  1. int main(array<System::String ^> ^args)
  2. {
  3.     try
  4.     {
  5.         if(args->Length>0)
  6.         {   
  7.             String^ filename = "ipyStrings";
  8.             String^ path = Assembly::GetExecutingAssembly()->Location;
  9.  
  10.             ScriptEngine^ engine = Python::CreateEngine();
  11.             ScriptScope^ scope = engine->CreateScope();
  12.             ScriptSource^ source = engine->CreateScriptSourceFromFile
  13.             (String::Concat(Path::GetDirectoryName(path), "\\", filename, ".ipy"));
  14.        
  15.             Console::WriteLine(args[0]);
  16.  
  17.             scope->SetVariable("passedArgs", args[0]);           
  18.             source->Execute(scope);
  19.  
  20.             Console::WriteLine(scope->GetVariable<String ^>("passedArgs"));
  21.         }                                   
  22.     }
  23.     catch(Exception ^e)
  24.     {
  25.         Console::WriteLine(e->ToString());
  26.     }
  27.  
  28.     Console::ReadLine();
  29.  
  30.     return 0;
  31. }

Python code:

Code Snippet
  1. import clr
  2.  
  3. print "Passed in: " + passedArgs
  4. passedArgs = passedArgs[::-1]
  5.  
  6. print "Sending back: " + passedArgs

Thursday, April 7, 2011

Random Numbers on a Bell Curve in C#

Have you ever wanted to generate some random numbers but with a distribution pattern other than the normal even pattern?

Well in a recent project I did.  I wanted a weighted distribution pattern that looked like a bell curve. 

I looked around yes there were some answers, but most got a lot deeper into math than I wanted or needed.  I simply wanted to generate a number with the probability that it was in the center of the range be greater than the probability that it was on the edges – in other words, it fit on a Bell Curve.

I cannot credit what post where gave me the simple solution, or I would post a link.  Here is a simple Extension Method to the Random class. 

It takes two parameters:

  1. Steps: How many numbers in each “Chunk” do you want.  If you want a number between 0 & 600 and set the Steps equal to 50, then the midpoint value (300) will be much more likely than 0 or 300.
  2. MaxValue: The possible range for the random number will be 0 to MaxValue - 1.

Now keep in mind that this is not mathematically perfect.  If you do not choose a step value that is a divisor of your MaxValue then you will not get the full range.  But, having said that, this is a great “Quick & Dirty” way to get a good approximation of a random bell curve.

Code Snippet
  1. public static class RandomExtender
  2. {
  3.     public static int NormalNext(this Random rnd, int Steps, int MaxValue)
  4.     {
  5.         int count = 0;
  6.         int val = 0;
  7.  
  8.         if (Steps < 1) return 0;
  9.  
  10.         while (++count * Steps <= MaxValue) val += rnd.Next(Steps);
  11.  
  12.         return val;
  13.     }
  14. }

Here is a picture of 20,000 random numbers with Steps = 50 & MaxValue = 600.

BellCurve

Monday, July 12, 2010

c++ dll error when using MD[d]

It is possible for any programmer, even one that has been in the "trade" for a loooong time, to be an absolute idiot - especially when they are learning something new. Not always does hard learned skills help when trying something new.

Take my latest gaff as an example. Now I've been coding C++/cli mixed mode dlls since 2005, but I'd taken some time off right before Windows 7 arrived. Well, it was time to get back into the saddle, so I started work on a long dormant project and got it to a Beta state.

I rolled out the debug dll to my testers and when they tested it on Windows 7, Boom!.

Ok, time for some research .... lots of time for research.

Well, I finally found - that in a non-/cli C++ dll, I could use the /MT compiler switch and it would work just fine on XP and Win7. But if I used the /MD compiler switch, which is required to use C++/cli, it would still run on a clean XP install, but not on a clean Win7 install.

Arrrgggg!

After many posts on many different forums, I decided to try making a install package (which I've NEVER had to do before - its just a dll after all!) but Visual Studio pulled in two additional files, that it said were needed to run.

Well - Success!! Sort of. But, I happily posted my results on the various forums. One reply (Thanks Peter) pointed out that they were Debug files and that it may be a licence issue if I were to disseminate them.

That got me to wondering if this was all a Debug/Release mode issue.

Well, it was. I started with a new copy of my Win7 Virtual PC that also installs the C++ runtime files.

I then pushed a debug version to it just to verify that we still had the issue. Yep.

Then I pushed a release version to it and viola! It works. Dumb, dumb, dumb!

Why do I make things so hard for myself?

Wednesday, July 7, 2010

C++/cli -> calling c# dll -> calling OpenFileDialog issue

I write extensions to a Cartography program called Campaign Cartographer 3 (CC3 for short). It is sold by one of the most involved companies I have ever had the pleasure to be associated with ProFantasy.

To program an extension to CC3, you need to be able to write old school windows dlls. You remember the ones! They have a DllMain function? I saw that shudder, you do remember.

Well, whenever I can I use C++/cli (the .net version of C++) and if the extension is very complicated, I do most of my coding in C# and reference the C# dll from C++/cli. You can mix and match plain old C++ and C++/cli (and C#) through IJW (Believe it or not, that stands for "It Just Works"). As a matter of fact all my newer extensions hook into C++/cli, even if I do not use it - I want it there just in case.

Well, in my latest project, a self-contained wiki-like document reader/writer (hard to explain - maybe in a later post), I needed to call the standard .net openFileDialog and saveDileDialog controls.

All of a sudden, I'm getting COM errors!?!?

'System.Threading.ThreadStateException' occurred in System.Windows.Forms.dll

Additional information: Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it. This exception is only raised if a debugger is attached to the process.


OLE calls? How old an error is that!?

Well, it seems that if you try to call the .net file dialogs from C++/cli you need to do it from a STA Thread. But, since I cannot access the main thread, remember this is someone elses application - all I have access to is my DllMain. Well, after searching around and asking about how to deal with this error on StackOverflow.com - I got my answer, sort of.

The helpful people over at StackOverflow pointed out that I needed to start my own thead as an STAThread. They also gave me advice on how to do this via COM.

Well, I'm not adverse to admit that the amount of COM knowledge I have could be held in a teacup. But the Thread advice solved the problem. I just did it the C++/cli way!

First you need to isolate the code you want to run into a class.

ref class StaClass
{
    void CallWiki()
    {
        WikiNotes::FrmWiki fw;
        fw.ShowDialog();
    }
}


Then from my main C++/cli code, I just create a new thread and call "CallWiki"

StaClass wiki = gcnew StaClass;

ThreadStart^ threadDelegate = gcnew ThreadStart(wiki, &StaClass::CallWiki);
Thread^ newThread = gcnew Thread(threadDelegate, 0);
newThread->SetApartmentState(ApartmentState::STA);
newThread->Start();


Remember though, if you want to wait until your new thread finishes, like I did, then you can:

while (!workerThread->IsAlive);
regularThread->Join();

Saturday, June 26, 2010

Fixing "Random" Default Button Behavior (asp.net)

Way back when I first started developing web applications, I quickly determined that you had to have the default button as the first submit button in the HTML markup.

A recent trouble ticket at work detailed that the default button was behaving erratically. It seemed that it was working only every other time. Yet, the location of the button never changed, so how could that be?

Here is a link of an example where I have recreated the issue.

Broken Default Button

To recreate the broken behavior, set the focus in one of the textboxes or a radiobuton and then press the enter key. The panel should minimize and a second panel should now become visible. click on the button in the upper right corner to re-expand the original panel and repeat the test.

every time both panels are visible, the default button switches to the button in the lower panel.

The fix is quite simple. Using asp.net 2.0 or higher simply add this one line to the Page_Load function: Page.Form.DefaultButton = "Button ID";

Fixed Default Button

Friday, June 18, 2010

Returning a string array to Javascript from Sliverlight

This took a lot of trial and error, but I finally figured out how to return to Javascript a string array. There where many different examples out on the web to call Javascript, passing a string array. But, no examples had Javascript calling a Silverlight function with a string array as the return value.

I first tried the direct approach:

javascript:
function TalkToSilverlight(data) {
var control = document.getElementById("silverlightControl");
var myStringArray = control.Content.Page.ReturningStringArray();
alert('length = ' + myStringArray.length + " : Value of First Element = " + myStringArray[0]);
}


Silverlight C#
public App()
{
HtmlPage.RegisterScriptableObject("Page", this);
//The rest I've elided
}

[ScriptableMember]
public string[] ReturningStringArray()
{
return new [] { "e", "i", "e", "i", "o" };
}


Well to make a long story short, a small little mention of the IList interface on MSDN was the key, all I "needed" to do (as opposed to all the changes I tried) was change the return value from string[] to IList.

Thursday, February 4, 2010

ASP.Net - Multiple Bin Folders support a plug-in website

It was way back in 2001 when I was tasked at my company to implement our internal web application in ASP.Net. This site not only reported on most of the company's critical functions but also contained very complex data management screens. The sheer size of the site precluded it from being in a single dot net solution.

So, after many hours of searching the Internet in vain for a solution, I finally started to experiment on my own. I discovered that any project could be added to the site by copying the compiled DLLs into the sites bin directory. This works, but it is not the most elegant solution.

Well, many years to late, at least for the company site, I've discovered a much more elegant solution. (And when I say I've discovered it, I mean that I've finally found the information on the internet :-))

Here is the link to the original information:
http://www.hanselman.com/

This post refers to ASP.Net 1.1, but I've taken the time to verify that this still does work in ASP.Net 3.5.

Saturday, January 30, 2010

StrSpn & StrCSpn in C#

After converting the c/c++ string tokenizing command strtok to c#, I thought I would look around to see there were any other interesting string commands in c/c++ that had not been integrated into c#. What I found was strspn and strcspn.

strspn (String Span) Returns the length of the longest substring that begins at the start of the string and consists only of the characters found in the supplied character array.

Code Snippet



  1. private int strspn(string InputString, char[] Mask)

  2. {

  3.     int count = 0;

  4.  

  5.     foreach (var c in InputString)

  6.     {

  7.         if (!Mask.Contains(c)) break;

  8.  

  9.         count++;

  10.     }

  11.     return count;

  12. }





strcspn (String Complement Span) Returns the length of the longest substring that begins at the start of the string and contains none of the characters found in the supplied character array.

Code Snippet



  1.     private int strcspn(string InputString, char[] Mask)

  2.     {

  3.         int count = 0;

  4.  

  5.         foreach (var c in InputString)

  6.         {

  7.             if (Mask.Contains(c)) break;

  8.  

  9.             count++;

  10.         }

  11.         return count;

  12.     }

  13. }



Monday, January 25, 2010

C# TechTip #1 Using MaxLength as AutoTab

So, for all those old VB6 programmers out there: Remember The Visual Basic Programmers Journal TechTip publications.

For me, those pamphlets where the most eagerly waited part of my VBPJ publication. Here are the links to PDF versions.

VBPJ TechTips #1
VBPJ TechTips #2
VBPJ TechTips #3
VBPJ TechTips #4
VBPJ TechTips #5
VBPJ TechTips #6
VBPJ TechTips #7
VBPJ TechTips #8
VBPJ TechTips #9
VBPJ TechTips #10
VBPJ TechTips #11
VBPJ TechTips #12

I learned sooooo much from these. The loss of these publications is just one of the reasons that VSM is just a shadow of VBPJ. Just for a walk through memory lane I read through some of them, seeing if any of them would apply to C# today. Most of the tips were not transferable, but a few could be.

So, here is the first "New" C# TechTip: Originally by Karl E. Peterson

How to add an AutoTab feature to textboxes that have a set MaxLength. Connect the textboxes' TextChanged Event to this function:


Code Snippet



  1. private void textBox_TextChanged(object sender, EventArgs e)

  2. {

  3. if((sender as TextBox).MaxLength == (sender as TextBox).TextLength) SendKeys.Send("{TAB}");

  4. }





Who knew that the Dot Net designers had included the SendKeys function!?!

Wednesday, January 20, 2010

Bye bye 1and1 - Hello GoDaddy!

I'm done. I've put up with 1and1's broken ASP.Net implementation. GoDaddy is even cheaper! Well, as I go through this painful experience - I'll keep everyone updated!

Now I can finally do all the things I've learned in ASP.Net 3.5. And, I'll be able to use 4.0 additions before I grow old!

Thank you GoDaddy.

And 1and1? Dudes, it has been five years now and you still have not gotten a full implementation of ASP.Net 2.0 up and running? Wow ...

Friday, January 15, 2010

Dynamically update Url Mappings in Web.Config

One of the most useful yet underused additions to ASP.Net 2.0 was Url Mapping. This feature alone has caused a lot of noise in the blogsphere. Complaints range from the fact that you need an entry for every mapping to the fact that the mappings are not dynamic because they reside in the static web.config file.

Well ... that is all true. It is also true that if you update web.config in code, the application object is restarted and users lose Session state.

But, if Url Mappings is say, used for a standard blog webpage:
  A - How many entries are in a Blog? Even if we are talking a thousand or so entries eventually, will that few lines cause the ASP.Net engine problems? I wouldn't think so.
  B - How often would the webmaster be updating the Url Mappings? Once per posting. Even if the visitors loose Session - its not like it is happening every hour or so.
  C - What is a simple site doing with Session in the first place?

Well, I'm adding Url Mapping to my personal website and I've got a page that when called will automatically update the Url Mappings in web.config from the database, but only when a new mapping is needed.

And yes, I have session and viewstate shut off!

Code Snippet



  1. protected void Page_Load(object sender, EventArgs e)

  2. {

  3. var config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);

  4. var section = (UrlMappingsSection)config.GetSection("system.web/urlMappings");


  5. var catArray = new ArrayList();

  6. var arcArray = new ArrayList();


  7. bool AnyChanges = false;


  8. foreach (var bd in BaseData.BlogDataList)

  9. {

  10. foreach (var strCategory in bd.Categories)

  11. {

  12. if (!catArray.Contains(strCategory) && !section.UrlMappings.AllKeys.Contains("~/" + strCategory))

  13. {

  14. catArray.Add(strCategory);

  15. section.UrlMappings.Add(new UrlMapping("~/" + strCategory, "~/Default.aspx?Category=" + strCategory));

  16. AnyChanges = true;

  17. }

  18. }


  19. var strEntryDate = bd.EntryDate.ToString("MMMM yyyy");

  20. if (!arcArray.Contains(strEntryDate) && !section.UrlMappings.AllKeys.Contains("~/" + strEntryDate))

  21. {

  22. arcArray.Add(strEntryDate);

  23. section.UrlMappings.Add(new UrlMapping("~/" + strEntryDate, "~/Default.aspx?Archives=" + strEntryDate));

  24. AnyChanges = true;

  25. }


  26. }


  27. if (AnyChanges) config.Save();


  28. Response.Redirect("~/Default.aspx");

  29. }

  30. }