Recently in C# Coding Tips Category

I once heard Chris Sells (in a podcast with Scott Hanselman) mention that the .NET Framework is so vast, that he was constantly uncovering objects/methods that he had already written himself.  Here's a few things that I discovered during the past year, thanks to my co-workers (Andy, Jon, Geoff).  Some of these items are so simple that I was embarrassed not to know about them.  Here is the list:

1.  The simple string.IsNullOrEmpty method. 

 if (string.IsNullOrEmpty(imageFileName))
   return false;

Before I encountered this, I was always writing C++ style tests like "if (string != null) && (if string.Length > 0)".  Doing both in one shot is a great piece of shorthand.

2.  The powerful Path object. 

Path.GetDirectoryName(filePathName);

One of the first things I did in C# was to port over a number of C++ methods that dissected a path string, chopping off the extension, returning the folder path, etc.  A nice exercise, but it was totally unnecessary.  The Path object has the following methods: GetDirectoryName, GetExtension, GetFileName, GetFileNameWithoutExtension.

3.  The beautiful BackgroundWorker object.

public class PSPUnpackWorker : BackgroundWorker 
{
    public PSPUnpackWorker()
    {
        WorkerReportsProgress = true;
        WorkerSupportsCancellation = true;
        DoWork += PSPUnpackWorker_DoWork;
    }

Have you ever wanted to perform a task in a background thread?  You can easily spawn off a worker thread on your own by creating a Thread object and calling Start.  But what if you wanted your worker thread to raise an event, to tell you it's completed step X out of 100?  And perhaps hook up this data to a progress bar control?

Don't do it the hard way, the .NET Framework is all setup to accommodate this pattern already with the BackgroundWorker object.

The ComicShowControllerDemo in the Crystal Toolkit has an example of a BackgroundWorker communicating to a ProgressBar control.  First, as shown above, I derive my own specialized class from the BackgroundWorker.  In the constructor, I set the properties in base class to true, WorkerReportsProgress and WorkerSupportsCancellation.  The former property allows me to call the ReportProgress method.  The control containing the ProgressBar can subscribe to the ProgressChanged event of the background worker and determine the percentage of completion.

PSPUnpackWorker _unpackWorker = new PSPUnpackWorker();
_unpackWorker.ProgressChanged += unpackWorker_ProgressChanged;
_unpackWorker.RunWorkerCompleted += unpackWorker_RunWorkerCompleted;
_unpackWorker.RunWorkerAsync();

When RunWorkerAsync is called, the DoWork method inside PSPUnpackWorker is executed:

void PSPUnpackWorker_DoWork(object sender, DoWorkEventArgs e)
{
    foreach (CrystalImageItem imageItem in Collector.GridModel)
    {
        if (CancellationPending)
        {
            e.Cancel = true;
            return;
        }        
        ....
        if (CanRaiseEvents)
        {
            float percent = ((float)++index/(float)Collector.GridModel.Count)*100f;
            int percentDone = Convert.ToInt32(percent);
            ReportProgress(percentDone);
        }
    }
    e.Result = true;
}

Inside the DoWork method, you can perform whatever tasks are required in the background worker.  I've sandwiched these between checking to see if a cancel action was requested at the beginning, and reporting the progress at the end.

4.  The mighty MethodInvoker object.

_imageForm.Invoke(new MethodInvoker(delegate
 {
     _viewerMain.SetImageInfo(imageInfo);
     _viewerMain.ToolTipText = imageItem.ToolTipText;

SetScale();
}));


In Windows Forms programming, you often encounter the problem of needing to update the controls on the main form, running in the main UI thread.  If you try to update these controls without using Invoke or BeginInvoke, you will no doubt encounter an error such as "Cross-thread operation not valid: Control X accessed from a thread other than the thread it was created on."

You could take the main Windows Form, test InvokeRequired, and then call Invoke or BeginInvoke.  You would have to create a delegate and pass this as a parameter.  The delegate would take care of calling the controls on the main form.

There's an easier way: use an Anonymous method, coupled with the MethodInvoker (as shown above).  Using this technique, it's like creating an inline delegate.  The code inside the delegate has access to the outerscope variables, such as imageInfo.  It's another great piece of shorthand.

When the code inside the delegate portion becomes too large, I will place them inside a new method, and call that method within the MethodInvoker:

ImageGridView.BeginInvoke(
    new MethodInvoker(delegate
    {
        InitInitialImageImp(index, ignoreGroupHeader);
    }));

You can find some other interesting tips about MethodInvoker and using invoke with UI controls on TimL's .NET Blog.

Here's a short but useful static funtion: converting a uint into a properly formatted hexadecimal string value in C#.

        public static string ConvertToHexString(uint value)
        {
            StringBuilder builder = new StringBuilder("0x");
            builder.Append(Convert.ToString(value, 16).PadLeft(8, '0'));
            return builder.ToString();
        }

This is pretty self-explanator, but the ToString method on Convert takes an optional second parameter for the base, which we sit to base 16 for the hexadecimal string value.  If you run this test code:

string test = ConvertToHexString(177);

The hex string value for 177 returned is: 0x000000b1.  The PadLeft method after the ToString call gives us the leading zeroes.  Without PadLeft, all we would see is 0xb1.

One of the things I wanted to achieve in Crystal Toolkit release 74 was the ability to sort my generic List<> of images (CrystalImageItem objects). I needed to be able to sort on many different properties within CrystalImageItem, and also to sort in ascending or descending order. Realizing that I probably needed to implement IComparer and IComparable, I decided that was way too much work, and my XBox Achivements score is really ridiculously low. A Google search on the topic lead me to this CodeProject article by Johannes Hansen on Dynamic List sorting. I found his approach intriguing, because he uses Reflection to key on properties within an object and use them as the basis for a compare operation. The resulting sort times are impressive, though I saw a couple of glitches reported on the CodeProject message board. Luckily, another programmer (Marc Brooks) took up the baton and released a C# library that includes a new, improved DynamicComparer. I highly recommend downloading Marc's library as it contains some nifty C# utilities.

Getting DynamicComparer to work was very easy. First, I had to make sure that the properties within the CrystalImageItem object were public, so that Reflection could find them. No problem there, I had four properties, two strings and two dates within CrystalImageItem:

public class CrystalImageItem
{
    public string ImageName
    ...
    public string ImageFormatString
    ...
    public DateTime LastWriteTime
    ...
    public DateTime CreationTime
    ...

To make it convenient to specify which property I wanted to sort, I created an enumerator called CrystalSortType:

public enum CrystalSortType
{
    ImageName = 0,
    ImageType = 1,
    CreationTime = 2,
    LastWriteTime = 3
}

The CrystalFileCollector is the controller class that manages a CrystalImageGridView and a CrystalImageGridModel. I created a public method called SortCrystalList, which takes a CrystalSortType enumerator, a boolean to indicate ascending or descending sort, and a boolean that tells the controller to redraw the grid (inside CrystalImageGridView) when the sort is completed:

public virtual void SortCrystalList(CrystalSortType sortType, 
  bool ascendingOrder, bool reDrawGrid)

The protected SortCrystalList method translates the enumerator key to a string and calls a final overloaded method:

protected virtual void SortCrystalList(CrystalSortType sortType, 
                                        bool ascendingOrder)
{
    string orderBy = string.Empty;

    switch (sortType)
    {
        case CrystalSortType.ImageName:
            orderBy = "ImageName";
            break;
        case CrystalSortType.ImageType:
            orderBy = "ImageFormatString";
            break;
        case CrystalSortType.CreationTime:
            orderBy = "CreationTime";
            break;
        case CrystalSortType.LastWriteTime:
            orderBy = "LastWriteTime";
            break;
    }

    SortCrystalList(orderBy, ascendingOrder);
}

The last version of SortCrystalList takes the string key, adds either ASC or DESC to the string (for ascending or descending sort) and creates the DynamicComparer. The List<CrystalImageItem> object inside the GridModel is sorted according to this key:

protected virtual void SortCrystalList(string orderBy, 
                                bool ascendingOrder)
{
    if (_gridModel == null)
        return;

    if (ascendingOrder)
        orderBy += " ASC";
    else
        orderBy += " DESC";

    // Create the comparer for Person types and define 
    // the sort fields.
    DynamicComparer<CrystalImageItem> comparer = 
        new DynamicComparer<CrystalImageItem>(orderBy);

    // Sort the list.
    _gridModel.CrystalImageList.Sort(comparer.Compare);
}

By default, CrystalFileCollector sorts the internal list by the ImageName property in CrystalImageItem. When the dynamic comparer object is created, the orderBy key looks like "ImageName ASC". If you read Johannes article, you will see that properties can be combined for more interesting sorts like "FirstName, LastName ASC". This is rather like doing a query on your objects, and so far the performance has been really good. You can naturally see that the Linq Project is going to make this sort of thing obsolete, but kudos to Johannes for coming up with this way back in December 2005.

In an earlier article (Accessing Embedded Resources using GetManifestResourceStream) I showed how to retrieve resources from an Assembly. In that particular case, the executing Assembly contained the embedded resource that we wanted to retrieve. What happens when the embedded resource is not in the executing Assembly? When it's located in a different C# Assembly, in a library built for controls or standalone classes? You can still do it, but you can't use GetExecutingAssembly.

In my case, I am building a library containing some Image controls, called CrystalUtils. This particular library contains a C# class for displaying Thumbnail images. When the control is used within the Visual Studio designer, I want to display a default thumbnail image. To access the default image, I have a class called CrystalTools which contains a static method called GetDefaultImage:

public class CrystalTools
{
  static private Bitmap _defaultImage = null;
  static private Image _defaultThumbnailImage = null;
  static public string DefaultImageName = 
        "CrystalUtils.resources.DefaultImage.bmp";

  static public Image GetManifestImage(Assembly theAssembly,
      string imageResourceName)
  {
    if (theAssembly != null)
    {
      Stream _imageStream;
      _imageStream = theAssembly.GetManifestResourceStream(
            imageResourceName);
      return new Bitmap(_imageStream);
    }

    return null;
  }

  static public Image GetDefaultImage(Assembly theAssembly)
  {
    if (_defaultImage == null)
      _defaultImage = (Bitmap)GetManifestImage(theAssembly, 
            DefaultImageName);

    return _defaultImage;
  }

GetDefaultImage takes an Assembly object as the first parameter. The Assembly object you pass cannot be the executable, you need to get the Assembly object that the caller knows contains the desired resource. In this case, a non-static object called CrystalFlipper is calling default image:

Image theImage = CrystalTools.GetDefaultImage(
    Assembly.GetAssembly(typeof(CrystalFlipper)));

Assembly.GetAssembly takes a Type parameter. Each C# class has its own unique type identifier. The typeof operator returns the correct type for the class CrystalFlipper. When I first tried this, I called it this way:

Image theImage = CrystalTools.GetDefaultImage(
    Assembly.GetAssembly(GetType()));

GetType() did work in my test application just fine. When I used it in a real application, I derived a class from CrystalFlipper and overrode some virtual methods. At that point, GetDefaultImage threw an exception. GetType() returned the type of the child class, not CrystalFlipper. While I could see that behavior working in different situations, in this case the typeof() operator gave me access to the same Assembly that my thumbnail classes originated from.

I've never been much of a graphics oriented programmer. Somehow I've always gotten by, using List and Tree controls, or various graphical toolkits to do my dirty work. Fortunately, GDI+ offers a lot of ways to draw your own content within a class derived from ScrollableControl if you need to do so. I wrote a control (which you will see here later in October) for viewing images in a horizontal slider, and everything looked great until I moved the scroll bar to the right. Instead of seeing the next set of images, I got a disjointed or improperly painted set of images.

After a day of trying to debug my code, I decided to go back to basics. I really didn't understand how to scroll a control and handle even the most basic painting events. I created a demo project called TestControlPaint (VS 2005, 38 K) :

Auto Scroll Test with a ScrollableControl

It has a class called TestControl (derived from ScrollableControl) which is designed to do one thing: draw a grid of 20 squares either horizontally or vertically.

/// <summary>
/// Tests scrolling a control horizontally and vertically
/// </summary>
public partial class TestControl : ScrollableControl

Within the class, there is a field called HorizontalMode, which can be set from the designer the comments tell you what it does:

/// <summary>
/// True means that the control displays horizontally; false means it displays
/// a vertical grid.
/// </summary>
public bool HorizontalMode
{
    get { return _horizontalMode; }
    set
    {
        if (_horizontalMode != value)
        {
            _horizontalMode = value;
            Invalidate();
        }
    }
}

In the picture below, I've put a horizontal Split Container into my Form, with one horizontal instance of TestControl in the upper panel, and a vertical instance of TestControl in the bottom panel. Horizontally we have squares 1-20 and vertically we have square 1-20 in 4 rows of 5 cells. Scroll bars magically appear and appear to work well! How did this happen? Some of the key steps were the following:

1. Make sure that the AutoScroll property is set to true on the control. It could set in the designer or in another method, but if it's not set somewhere, none of this will work:

AutoScroll = true;

2. Set AutoScrollMinSize to the virtual size of the content within your control:

// Set the auto scroll size to the total width and  
// height of the content drawn within the control.
AutoScrollMinSize = new Size(_cumulativeWidth, 
                            _cumulativeHeight);

3. In your OnPaint method override, call TranslateTransform with the current AutoScrollPosition:

//handle possibility that the viewport is 
//scrolled,adjust my origin coordintates 
//to compensate
Point pt = AutoScrollPosition;
gfx.TranslateTransform(pt.X, pt.Y);

The first two bullet items I had figured out from reading books and articles, but the third one eluded me. TranslateTranform, as soon as I put it in my code, made the scrolling work instantly. This makes sense when you see what I was drawing within OnPaint:

// Create the grid...
for (int index = 1; index < (_numSquares+1); index++)
{
//...
    // Calculate the coordinates for a square rectangle
    Rectangle theRect = new Rectangle(_squareWidth * 
        (startX++) + _margin, startY, 
        _squareWidth, _squareHeight);
    //...
    // Draw the rectangle with a black brush
    Pen borderPen = new Pen(theBrush);
    gfx.DrawRectangle(borderPen, theRect);

A series of squares are drawn: from 0 - 100, 105 - 205, 210 - 310, etc. When a paint message is received, the control drew the first few visible squares correctly. What happens when you need to draw square 4 at starting location (315, 5) and the client area is only 250 wide? Without TranslateTransform, the Graphics object (gfx in this case) cannot draw anything beyond the client rectangle of the control. BTW, I forgot where I saw TranslateTransform, but it was Bob Powell's comment on a message board that gave me the clue to look into this.

Speaking of Mr. Powell, he helped solve another problem. When you have a virtual drawing surface, how can you accurately determine the mouse coordinates? OnMouseClick only returns the mouse coordinates within the client rectangle, not from your virtual rect setup with AutoScrollMinSize. To get the virtual mouse location, take a look at Powell's Back-track the mouse example. He takes the AutoScrollPosition and transforms it into the virtual mouse location. I've included this method in TestControl.cs:

/// <summary>
/// Gets the mouse location according to the virtual 
/// position in the control.
/// </summary>
/// <returns>The virtual mouse location</returns>
protected Point GetVirtualMouseLocation(MouseEventArgs e)

TestControl receives a mouse click event in the OnMouseClick override. It calls GetVirtualMouseLocation for the virtual location, and passes this Point object to a method called getSquareID:

// get the virtual mouse location using the transforms
Point mouseLocation = GetVirtualMouseLocation(e);

// Translate the virtual mouse location into a square ID
int squareID = getSquareID(mouseLocation);

StringBuilder strBuild = new StringBuilder();
strBuild.AppendFormat("You clicked on Square ID {0}", 
                        squareID);

// if we found a valid square, show the id in 
// the message box
if (squareID > 0)
    MessageBox.Show(strBuild.ToString());

The test Form will display the ID of the square that you click on within either the horizontal or vertical forms. This simple technique worked equally well within my larger, more complex control.

Download:
TestControlPaint VS 2005 Project (38K)

How do you access resource files (bmp, mp3, etc) that are compiled into your Windows Forms executable? After googling the subject, the Assembly object's GetManifestResourceStream method seemed to be the solution. MSDN's entry on this subject makes it seem relatively simple. However, it took me over an hour to get it to work in my latest project. There are two things you must do in other to access an executable's resources:

  1. You must know the exact name of resource (mynamespace.resource.resourcename).

  2. You must embed the resource into your executable.

Accessing the resources means that you must have access to the executable's Assembly object. I cached this in the Form's Load event:

Assembly _assembly;
_assembly = Assembly.GetExecutingAssembly();

The image file that I was trying to access in my program was called Image1.bmp. I made a call to GetManifestResourceSteam like this:

imageStream = _assembly.GetManifestResourceStream(
    "ThumbnailPictureViewer.Image1.bmp");

The problem was that _imageStream was always returning NULL. Digging a little further, various articles mentioned that my decorated name might be incorrect. Perhaps I was using the wrong namespace, or the case sensitive name might be wrong? The only way to determine this was to use GetManifestResourceNames(). You can retrieve a collection of string resource names and dump them out to the console:

string[] names = _assembly.GetManifestResourceNames();
foreach (string name in names)
    System.Console.WriteLine(name);

The console showed me a few resource namespaces, but no embedded objects! Even had Image1.bmp clearly in my Solution Explorer, and in my Project properties, Resources tab, it never showed up. The trick in getting this to work is to make certain that Image1.bmp was set to Embedded Resource in the Properties window:

Build Action should be set to Embedded Resource

When you create resources in Visual Studio 2005, they are linked to your executable by default at compile time. This is a nice option if you want to keep the resource files separate from the .resx file, allowing other people to change them. If it needs to be accessed programatically with GetManifestResourceStream, it has to be Embedded into the .resx file. The only drawback here is that my Image resource can only be changed within Visual Studio 2005. Once I changed the Build Action to Embedded, I saw the correct name in the output window:

ThumbnailPictureViewer.resources.Image1.bmp

And then my code to load Image1.bmp into a Bitmap object worked successfully:

Stream _imageStream;
_imageStream = 
    _assembly.GetManifestResourceStream(
    "ThumbnailPictureViewer.resources.Image1.bmp");
Bitmap theDefaultImage = new Bitmap(_imageStream);

External Link:
MSDN summary on Linked vs. Embedded resources.