Arbitrary Sorting Order in Linq To SQL

I ran into a situation recently that took me some time to work out and thought I’d document here. I have an older ASP.NET Web Forms application I help maintain. Some upgrades and changes to the workflow used by the customer had meant a few assumptions I’d made no longer applied.

The biggest of these was that a list of values no longer returned from the database the way I’d assumed before. Here is the Linq to Sql that pulled the values to that point.

   1:  var plans = from m in dc.MenuPlans
   2:              where m.client == CurrentClient && m.year == year &&
   3:                  m.month == month && m.day == day
   4:              select m;

As you might guess from this code, it pulls a set of menu plans from a database for a client. Each menu plan is specific to a day. What you can’t see here is that each meal has a meal name that is simply “Breakfast”, “Lunch”, “Dinner”, or “Snack”. Before the meals had been entered in that order and the creation method ensured they showed up in the order being entered.

Now they were being entered in a different order by multiple people and the order of creation no longer worked. The desired order was still breakfast, lunch, dinner, and then snack at the end. Sorting simply by the column wouldn’t work as that would produce an alphabetical order resulting in breakfast, dinner, lunch, and then snack. Close, but not quite.

What I needed was a custom ordering sequence. I could pull the items over in four groups and then append them to a final list, but that seemed messy and slow. I wanted a solution to do so at the database and not have to bring the elements in and sort in memory. I finally worked out a nice solution with this code.

   1:  var plans = from m in dc.MenuPlans
   2:              where m.client == CurrentClient && m.year == year &&
   3:                 m.month == month && m.day == day
   4:              orderby m.mealname == "Breakfast" ? 1 :
   5:                 m.mealname == "Lunch" ? 2 :
   6:                 m.mealname == "Dinner" ? 3 : 4
   7:              select m;

The new code lies on lines 4-6. What I do is compare the element that I want to sort by to the values in the order I wish things to show. I’m using the binary operator here. If you’re not familiar with it, this works like a compact if/then statement. The binary operator:

   1:  return x > 0 ? 0 : 1

Is equivalent to the following if/then statement.

   1:  if(x > 0)
   2:     return 0;
   3:  else
   4:     return 1

So the code lets me map the string values to numeric values arbitrarily. Breakfast maps to 1, Lunch maps to 2, Dinner maps to 3, and any other value to 4. Since the result of this is a set of integers, the ordering works the way I want.

While the code looks a bit messy, it translates nicely to SQL that runs on the database server through a CASE statement and I get the order I want without any extra processing in the web application.

Fixing Error when Building Windows Phone Apps on Network Drive

I’m working on building a Windows Phone application and ran into an interesting error that took some time to track down and I thought I’d share the fix here. I normally develop on a Windows virtual machine running on my MacBook. To make backups simpler and to sharing files between machines easier, I map the documents of the virtual machine to the MacBook’s documents folder. This means that my documents folder inside the VM appears to be on a network drive.

When I tried to compile my phone app for the first time I got an error similar to this:
Error : Could not load the assembly
Path to Assembly\MyApplication.dll.
This assembly may have been downloaded from the Web. If an assembly has been downloaded from the Web, it is flagged by Windows as being a Web file, even if it resides on the local computer. This may prevent it from being used in your project. You can change this designation by changing the file properties. Only unblock assemblies that you trust. See http://go.microsoft.com/fwlink/?LinkId=179545 for more information.

This belongs on the all time list of bad Microsoft error messages in that it not only is wrong, it’s downright misleading. the article discusses assemblies downloaded from the web. In my case the problem couldn’t have anything to do with the assembly being downloaded form the web. First the assembly in question is one that I’m trying to compile. There is no option to unblock as the article suggests as a fix.

I finally figured out the problem comes from the assembly, and my whole project, resides on a network drive as far as Windows is concerned. The first and most common fix I found was to move the project to the local hard drive. That wasn’t my first option so I looked into alternatives.

I finally found an article on Microsoft’s web site that gives a fix at http://msdn.microsoft.com/en-us/library/dd409252%28VS.100%29.aspx, but even this article has problems. It tells you to ignore it in the header and refers to the other article in spite of it being the actual fix for what’s probably a more common problem (purely my speculation, but I feel more people are probably accessing assemblies on a network drive than downloading them from the Internet). It also doesn’t really tell you where to apply the fix. The change needs to go into the devenv.exe.config file under C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE (or C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE if you’re running a 64 bit OS). Under Windows 7 the file and folder are protected making the file a bit tricky to edit so here’s the process I used.

  1. Copy the devenv.exe.config file from the appropriate IDE path for your OS to a directory you have full rights to (your documents folder for example).
  2. Open the copy of the file in a text editor (Notepad for example) and look for the line
    <runtime>
    which will be close to the top of the file.
  3. Directly under this line add the following line
    <loadFromRemoteSources enabled=”true”/>
  4. Save the changed file.
  5. Now copy the edited file from your temporary directory back to the directory you moved it from. You will be told it requires admin rights and have to grant them. Do so.
  6. Restart Visual Studio and it works.

Skinning a Windows Form Application

The normal application window looks like a simple, basic rectangle.  For most uses it works quite well though providing a nice and familiar wrapper for a program.  It’s a bit boring though.  Sometimes though you create a program that doesn’t quite fit the normal square window.  Maybe you’re creating a custom display.  Whatever the reason, you are not limited to the standard window look.

I recently started updating and cleaning up a few applications I’ve written for my own use.  One of them works as a target to drag files onto and really cried out for something other than a square window.  I decided to create a nicer interface and in this post I’m going to show how to create a Windows form application with a custom look.

Step One: Tear Down the Default Form

When you skin a window, some of the things that Windows normally does for you now have to be done manually. Before we apply our custom look, we’ll start by getting rid of things we don’t want and then recreating those lost elements.  Let’s start with the form that you get when create a new Windows Form application in Visual Studio 2010. It looks like this when you run the application.

clip_image001

We want to get rid of the menu bar and those buttons in the top right window.  We can easily do this by changing the window type. In the form’s properties Change the FormBorderStyle attribute from the default Sizable to None.

clip_image002

If you run the program at this point you will get a plain grey window.  If you try to click on the window and move it, you will find it ignores your request. If you try to resize the window, that also will not work. You will also find nothing to click and exit the application.  By changing the border style to none, we also lost the built in support to move the window, close the application, and resize the window.

Step Two: Recreate Lost Functionality

We therefore need to add any of these features that we want the user to have. At the least we should give the user a way to close our program. For simplicity, I’m going to add a handler so that if someone right clicks on the window, the program exits.  In a real program, right clicking might bring up a context menu with an exit option.  The method it’s invoked doesn’t matter as this code will close your application.

        private void SkinnedWindow_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                Application.Exit();
            }
        }

If you now run the program, you will again see a simple gray square.  If you right click on the window, the application will nicely exit.

In most cases we will still want to allow the user to move our application.  I found a good way to allow moving a skinned windows is to start the move when the user presses the left mouse button while on the window. They can then move the window while they hold the left button down. When the user releases the left mouse button, the window will remain at that location.

To implement this, the application needs to handle the MouseDown, MouseMove, and MouseUp events for the form. In addition, we’ll need to keep track of when we’re moving or dragging the window and the form’s location when we start moving it. So we’ll add two variables to the form class store this information.

        private Point _offsetPoint;
        private bool _dragging;

When the user clicks the left mouse button on the window we simply want to note that we’re entering a state where the user is moving the window and store the initial location where the user clicked the mouse.

        private void SkinnedWindow_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                _offsetPoint = new Point(e.X, e.Y);
                _dragging = true;
            }
        }

In the MouseMove event we first check to see if we’re moving the window by checking the bool we set when the left button was clicked. If so then we’ll take a note of the current location of the mouse and convert that to a screen point.  We then set the form’s location to this new point which is the difference between this screen point and the original locaiton.

        private void SkinnedWindow_MouseMove(object sender, MouseEventArgs e)
        {
            if (_dragging)
            {
                Point mousePoint = new Point(e.X, e.Y);
                Point screenPoint = PointToScreen(mousePoint);
                Location = new Point(screenPoint.X - _offsetPoint.X, screenPoint.Y - _offsetPoint.Y);
            }
        }

When the user releases the left mouse button, we just need to note that we’re no longer moving the window by setting our flag to false.  Our form location is already where we want to leave the form.

        private void SkinnedWindow_MouseUp(object sender, MouseEventArgs e)
        {
            _dragging = false;
        }

If you run the program now, you’ll still see a gray window.  You can still right click and exit as before.  Now you can also move the form around. If you click inside the window and hold the mouse button down, you can drag the window around the screen. When you release the button the window will stay where it was.

In my application, I did not want the user to arbitrarily resize the window. In my application, I provided a context menu the user can select from a few predetermined sizes. When the user selects a size I set the size of the window using the Size property for the form. You could also do something similar to how we handled moving the window if you want to give the user more flexibility on resizing the window.

Step Three: The New Look

We’ve now implemented the basic functionality we’d lost so we can now focus on making the window look how we want. For this sample, I’m going to select an image from the Visual Studio image library.  I’m using the 007_PrintView_128x128_72.png image located in the library under Actions\png_format\WinVista. You can be any image, but for simplicity it should be a format that natively supports transparency for areas that are not part of the image.

clip_image004

First add the image to our project as a resource. To do this, go to the Project’s properties and select the Resources tab. Select Add Resource -> Add Existing File…. In the dialog that opens find and select the image that you wish to use for your application’s appearance. You will see a new Resources folder appear in the project and our graphic will appear under it. We can now reference this resource in our program when we want to draw the image.

In our case we want our entire window to appear as this image. Since the image I am using is 128 x 128 and I am not going to let the user resize the window, I will set the window on startup to this size. I can do this by going to the Properties of the form and setting the size to 128, 128 which the window the form to same size as the graphic that I’m using.

clip_image005

I will use this graphic as my window.  To give my form this custom look I implement the Paint event of the form.  In the Paint event, I first load the image. Here I’m doing it from the image resource.  You could also add the image as a file in the project and create the image from that file.

The code below will always resize the image to fill the window.  It changes a few settings to improve the quality of the resizing.  Since we above set our window size to 128 x 128, the same as the image, no resizing will be needed.  To see the effect of this, you can change the size of the window to a different value and the image will be scaled appropriately.

        private void SkinnedWindow_Paint(object sender, PaintEventArgs e)
        {
            // Get Image from resources
            using (Image folderImage = Resources.Network)
            {
                // Set to high quality and draw image onto background
                e.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                e.Graphics.DrawImage(folderImage, 0, 0, Width, Height);
            }
        }

We’re almost there.  If we run the application now our window appears.  We see our graphic, but they gray background from the form still shows.

clip_image006

Our last step is to get rid of the form background. We do this by setting the background color of the form to a know value. By default it is set to the Control value which can be changed by the user if they customize the appearance of Windows or use a Windows Theme. Since we want our form background to always be transparent we’ll change this to a known value. The form property we need to change is BackColor and here I’m changing the value to white.

clip_image007

Next we want to set the TransparencyKey property to match this new BackColor property. This property tells Windows to treat any part of the form that is this color as transparent and let whatever lies under it show through.

clip_image008

After this change when we run our application, we get a nice transparent window that looks just like our image. Below you can see the image placed on top of Visual Studio 2010. Notice that the transparent parts of the image are not considered part of the form. If we right click or left click and drag in the top right area just above the printer, it does not register as a click on our form and will bring up the application behind ours.

clip_image009

You can download a sample project with this code for VS 2010 .

Balancing Rest and Motion

Saw a post on gapingvoid simply titled “Now What.”  I think it’s a good question to ask yourself every so often.  Something about the end of the year invites this type of reflection. You’re only one day older on January 1 than you were on December 31 just as you’re only one day older on your birthday than you were the day before. Though arbitrary, the change from one year to another feels significant. Maybe it’s the increased interactions with friends and family during the holiday season. Maybe it’s the shift back to normal life after the hectic rush of the rest of December.

I’ve heard, “this year has flown by,” so many times in the last couple months that I’ve lost count. I’ve normally nodded my head and agreed, but in truth this felt like a very long year for me. Not always in a bad way as I’ve had some wonderful and amazing experiences this year, but more than once challenges in my personal or professional life made me aware of every passing moment while waiting for a shoe that didn’t drop or didn’t land where I’d hoped. I’ve faced as much disappointment as joy this year, which has been a change for me.

Around this time last year I became aware of several things I did not like about my life. So like any good modern self-improvement minded person, I set about changing them. We all make resolutions that mostly fall by the wayside, but mine began quite well. I established new patterns in eating and exercise and for the first time I started winning the fight with my weight. With those early successes I began looking at other areas in my life and working to “fix” the problems I saw.

February and March both brought shocks to my life, one suspected and the other completely out of the blue. The first brought pain and the second brought happiness along with heartbreak.  As I moved into summer, I became fixated on the improvement. I wanted to fix everything in my life. I threw myself into everything that seemed wrong and worked on making it right.

It seemed a great idea at the time.

In truth there have been some wonderful results of this process. I’ve dropped my weight from peak near 300 pounds to nearer 240. I’m fitting into suits I bought for my interviews while a senior in college. I’m buying new clothes because I need something smaller for the first time in my life. I fully expect that by the time late spring rolls around I’ll be rather close to my “idea” weight probably for the first time since I was a freshman in college.

There are other things of course. I’ve rebuilt social ties and friendships I’d let lapse. I again found the joy in experimenting and trying new things. I developed a new good friendship. I’ve improved the skills in my photography hobby to the point I actually wrote an eBook on my niche. I’ve even sold a few copies.

The mistake came as I stopped enjoying where I was. I became so focused on the process of improving and where I wanted to go, I stopped enjoying where I was. Perhaps I’d been unhappy with my state for a while as the shift came subtly. I never noticed. I realized I was unhappy, but not why. Of course I was unhappy with some things that I wanted to change, but I stopped noticing the wonderful people and experiences in my life. I was like the driver so focused on getting to a meeting on time and complaining about the traffic, he misses the beautiful sunset.

By fall it had become obvious something was amiss. A Buddhist proverb reads something like, “When the student is ready, the master appears.” I didn’t find a single master to provide the answers. I got snippets here in and there, and then I had a wonderful, deep conversation with a good friend one October afternoon. She said the exact words that I needed to hear. It took a couple days to really sink in, but that was the “Aha!” moment. I found other things that provided direction. I particularly recommend The Happiness Hypothesis: Finding Modern Truth in Ancient Wisdom  which is a wonderful blend of religious thought, philosophy, and brain science.

It wasn’t an overnight change, and it took me a couple weeks to realize I’d turned that corner. Since that day I’ve enjoyed life more, maybe more than in several years. I’ve learned to live in the moment, savor the small moments in life, to enjoy the flow of my senses coming in. When I’m eating, I enjoy the flavor and texture of my food instead of throwing it down. When I’m with friends, I enjoy the conversation and belonging and don’t worry about what I’m going to say or what we’re going to do. When I’m doing other things, I enjoy them fully and completely.

I still make goals and plans. I still have things I want to pursue. For getting lost along the way, I did still reach many of my destinations. The change is that now while I still am heading somewhere, I’m enjoying the drive along the way.