# Wednesday, April 14, 2010

Today, after studying for a CS exam for four hours straight, I decided that it would be a good judgment call to write some code. After all, there’s only so much theory one can absorb until code calls. So, I decided to write my first (official) demo. I’m still working on it, and want to compose my own music to it (and make it suck a little less), so it’ll be released later.

I ran into a fun snag along the way, though. I used the SDL libraries to power the graphics of the demo. One library, SDL_Gfx, is not distributed precompiled – you have to compile it yourself. Fortunately, the author includes a Visual C++ Project file that builds just fine. Now, I’ve done some SDL work in the past and had built SDL_Gfx a while ago.

At this point, some readers might see where this is going. As I put some of the hacking finishing touches on the demo, I sent it out to a couple of friends. Of course, it didn’t run on either machine. One was Windows 7, one was Windows XP, and both failed with the same error: The application was unable to start correctly (0x0150002).

A little digging, and the problem pointed to a few solutions – reinstall Windows (yuck), install Visual C++ Express 2008 (double-yuck), or redistribute the debug DLL for Visual C++ 2008 (triple-yuck). This seemed odd to me; I had compiled the demo as a release, non-debug Windows EXE. Why on earth would it need the debug runtime?

Further digging in the event log brought us this error: "Activation context generation failed for "c:\…\release\SDLGFX.DLL". Dependent Assembly Microsoft.VC90.DebugCRT, processorArchitecture="x86", publicKeyToken="1fc8b3b9a1e18e3b", type="win32", version="9.0.21022.8" could not be found. Please use sxstrace.exe for detailed diagnosis."

After a couple of hours of fiddling with manifest files, swearing at SxS, and no luck with the various builds, I stared at the path above. SDLGFX.dll. Then it hit me.

I had built SDL_Gfx as a Debug library in Visual C++ 2008. Crap.

Some swearing and frantic coding later, it works, and runs on other machines. The moral of the story? Always check to make sure your library build type matches your solution type.

I just wish I could have that two hours of my life back.

Wednesday, April 14, 2010 4:12:11 AM (Eastern Daylight Time, UTC-04:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, November 26, 2009

For anyone who’s done any WPF control retemplating, it can sometimes be a daunting task. Some controls seem to retemplate with ease, while others can have a myriad of nested styles, with certain parts seeming to appear where you don’t expect them. Today, I ran into an interesting situation with the WPF Toolkit’s DataGrid – retemplating the column header sorting arrows.

As it turns out, the arrows for column sorting live in the control DataGridHeaderBorder. If we inspect the DataGrid.DataGridColumnHeader style in Blend…

Blend1

…notice there’s no placeholder for the arrows. Attempting to edit the default style for the Border won’t work either – there is no style to be found. There is no ControlTemplate to edit either, since DataGridHeaderBorder inherits from Border, which in turn inherits from FrameworkElement, and not Control. (Remember, Control defines the ControlTemplate property)

So where are the arrows defined then? Well, inspecting the source for the DataGridHeaderBorder…

/// <summary>
///     Called when this element should re-render.
/// </summary>
protected override void OnRender(DrawingContext dc)
{
if (UsingBorderImplementation)
{
    // Revert to the Border implementation
    base.OnRender(dc);
}
else
{
    // Choose the appropriate rendering based on the current theme
    switch (Theme)
    {
      // Omitted for brevity's sake...
      // A switch here calls RenderAeroNormalColor.
    }
}

private void RenderAeroNormalColor(DrawingContext dc)
{

   if (isSorted && (size.Width > 14.0) && (size.Height > 10.0))
   {
       // Draw the sort arrow
       TranslateTransform positionTransform = new TranslateTransform((size.Width - 8.0) * 0.5, 1.0);
       positionTransform.Freeze();
       dc.PushTransform(positionTransform);

       bool ascending = (sortDirection == ListSortDirection.Ascending);
       PathGeometry arrowGeometry = (PathGeometry)GetCachedFreezable(ascending ? (int)AeroFreezables.ArrowUpGeometry : (int)AeroFreezables.ArrowDownGeometry);


          // Actual drawing here, omitted for brevity's sake...
      }
}

If you snoop through this source (in the toolkit), you’ll notice the arrows are drawn in the OnRender() method of the DataGridHeaderBorder. In my humble opinion, I don’t think this is the most intuitive way to pull this effect off, but I’m sure there was a sound reason for it. In any case, if you’ve got your own sorting arrows that you wish to use, the easiest (and only way, I believe) to do this is to adjust their visibility by using the Triggers of the DataGridColumnHeader, namely the SortDirection property.

Special note: SortDirection is a nullable property – it is set to null when there is no sorting applied to the column. Keep this in mind when templating the control.

image For this demonstration, I’ve blown away the default DataGridHeaderBorder. I’ll use a regular Border, with a ContentPresenter within it (for the column header contents – don’t forget this), and two TextBlocks to indicate the sort direction. Remember, you aren’t limited to TextBlocks – you can use whatever you want to indicate sort direction. You can even use Storyboards that fire on the EnterAction property of the trigger to provide animations.

First, I created a style on the DataGridColumnHeader of a fresh DataGrid, and defined it in Window1.xaml. I blew away the default style and put in a Border containing a StackPanel, which contains the ContentPresenter and our two TextBlocks.

The TextBlocks are to be Collapsed by default, since the default state of a column is no sorting.

The reason I picked a StackPanel to contain the ContentPresenter and the sorting arrows is that I wanted to whip up a demo fairly quickly, and this is the fastest way to get the control to automatically resize itself to prevent waste of dead-space from the arrows. You can pull off the hiding of the space used by the arrows by using appropriate autosizing of grid columns, etc., a topic of which I’ll cover in a future article.

Next, we can apply our triggers to show the user what direction they are sorting. In the above screengrab, I’ve already added three Property triggers for  SortDirection: Ascending, Descending, and null. Null is used for when there is no sorting applied, and the other two are self-explanatory. So, depending on which value is currently set will define which arrows are visible.

With SortDirection = Ascending selected, I’ve set the Visibility property of the Up TextBlock to be visible, and for the SortDirection = Descending, the Dn TextBlock is visible. When null, no changes occur from the default style, which is to say both TextBlocks are Collapsed. The end result looks like this…

 

 image which goes to…  image

… and finally goes to…

image

Thursday, November 26, 2009 11:32:16 AM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  |