Visual Studio Power Commands

Power Commands is a free and extremely useful plugin for visual studio. Among its many features is ‘Collapse All’ so that you can collapse the solution tree in the solution explorer and ‘Open Command Window’ to open a command window in the directory of the selected project. These are the two features I use the most and prove invaluable as the solution I use at work has 91 projects attached to it … this can be really painful to navigate when a number of the projects are expanded. Well worth the download …

Download Here

SQL Search

Ever wanted to be able to search your sql databases for procedure names, table names etc as you would with a file search? Well now you can with this handy little tool from Redgate. Its a free download and has to be one of the handiest Sql tools I have come across especially when working with multiple large databases.

Download SQL search

Comma Delimited Lists

We are commonly required to handle comma delimited lists while developing applications. In the past, I have used for loops or Array.Split() to handle these situations. At least I did until I discovered a handy little class in the .NET framework that is there to handle just such situations. The CommaDelimitedStringCollection class in the System.Configuration namespace behaves just like a normal generic list including methods for Add, Remove, IndexOf, Count, etc and can be looped through like any other list. This allows the flexibility of searching and sorting and also simplifies the handling of empty lists and removal of trailing commas when returning the comma delimited string. To convert to the comma delimited string all you have to do is call ToString() and you’re done.

More information can be found here

 
int i = 1;
string str1 = "A String";
string str2 = "Another String";
 
//assume System.Configuration has been imported
CommaDelimitedStringCollection strList = new CommaDelimitedStringCollection();
strList.Add(i.ToString());
strList.Add(str1);
strList.Add(str2);
 
Console.WriteLine("Count = " + strList.Count.ToString()); //output => Count = 3
Console.WriteLine("Index of '1' = " + strList.IndexOf("1")); //output => Index of '1' = 0
Console.WriteLine(strList.ToString());  //output => 1,A String,Another String

Extension Methods

Extension methods are a handy feature that allows you to extend the functionality of existing classes for which you do not have the source. Extension methods must be static and the type following the ‘this’ keyword indicates the type that is extended by this method.

More information on extension methods can be found here

These are just some of the extension methods I commonly use to make everyday coding a little easier and more readable.

/// <summary>
/// Reformat a string so that the first letter of every word is capitalised and every other letter is lower case
/// </summary>
/// <param name="str">String to format</param>
/// <returns>Formatted string</returns>
public static string ToTitleCase(this string str)
{
    CultureInfo ci = new CultureInfo("en");
    TextInfo cc = ci.TextInfo;
    return cc.ToTitleCase(str);
}
 
/// <summary>
/// Convert this string to its enum type
/// </summary>
/// <typeparam name="T">Type of enum</typeparam>
/// <param name="enumValue">string value to parse</param>
/// <returns>Enum type parsed from string</returns>
public static T ConvertToEnum<T>(this string enumValue) where T : struct
{
     if (!typeof(T).IsEnum) throw new InvalidEnumArgumentException("T must be an enum");
     return (T)Enum.Parse(typeof(T), enumValue, true);
}
 
/// <summary>
/// Get the value of a table column from a reader object
/// </summary>
/// <typeparam name="T">Type  of expected return value</typeparam>
/// <param name="reader">Reader oject to get the value from</param>
/// <param name="columnName">Name of column to retrieve the value from</param>
/// <returns>Column Value</returns>
/// <exception cref="NullReferenceException">If T is not nullable and the column value is null</exception>
public static T GetColumnValue<T>(this IDataReader reader, string columnName)
{
       if (reader.IsDBNull(reader.GetOrdinal(columnName)))
       {
           if (
               (typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>))
               || typeof(T) == typeof(string)
              )
           {
               return default(T);
           }
           else throw new NullReferenceException("DB Value is null");
       }
       else return (T)reader[columnName];
 }
 
//The above methods are called like this ...
string myStr ="exAmple sTrinG";
Console.WriteLine(myStr.ToTitleCase()); //Output --> Example String
 
//assume we have the namespace Microsoft.SqlServer.Management.Smo imported
string varChar = "VarChar";
SqlDataType testVrChr = varChar.ConvertToEnum<SqlDataType>();
 
//where reader is an IDataReader
int? value = reader.GetColumnValue<int?>("ColName");

Windows UI Threading

Using background threads to handle long running processes such as fetching data from the db should be common practice when developing windows forms. Failure to do so will result in a clunky UI that will lock up and may appear as crashed to the user. It also allows you to do nice things like updating progress bars etc.

A common trap is trying to call a method which updates a UI control from a background thread. This will result in the “Cross Thread Call” exception which can frighten many developers away from threading in the IU. Here is a pattern I tend to follow when threading UI that takes a lot of the mystery out of things and keeps the UI running smoothly.

First we have a method that calls a long running process. In this method we simply create a new thread in which to run the process and get it started.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/// <summary>
/// Do some long running process on a background thread
/// </summary>
private void Start()
{
     lbl.Text = string.Empty;
     Thread worker = new Thread(DoSomething);
     worker.Start();
}
 
/// <summary>
/// Long running process 
/// </summary>
private void DoSomething()
{
     for (int i = 0; i <= 100; i+=5)
     {
          UpdateProgressBar(i);
          Thread.Sleep(500);   
     }
}

In each iteration of the loop we update the value of a progress bar. This however can only be achieved on the UI thread and this method was called on the background thread. Normally this would throw an exception as the invoke keyword is not used but because of the way the UpdateProgressBar method has been written this is not an issue.

The code below shows how to write any method that updates a UI control so that it can be called safely from any thread and will always execute on the UI thread no matter what the thread the caller is on.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/// <summary>
/// Something that updates a UI control that 
/// might be called from a background thread 
/// </summary>
/// <param name="progress"></param>
private void UpdateProgressBar(int progress)
{
     //Wrap any code that updates a UI control in this anonymous delegate
     Func<int, object> work = delegate(int progressCount)
     {
        if (progressCount < 0) progressCount = 0;
        if (progressCount > 100) progressCount = 100;
        progressBar1.Value = progressCount;
        if (progressCount == 100) lbl.Text = "Done!";
        return null;
     };
 
     //Check if we are running on a background thread and if so use Invoke
     //otherwise just call the delegate
     if (this.InvokeRequired) Invoke(work, progress);
     else work(progress);
}

The Func is an anonymous delegate … all logic that affects controls should be wrapped in this. The last two lines handle the differing threads. InvokeRequired determines if we are on the UI thread or the background thread. If we are on a background thread it will return true and we call Invoke on the anonymous method to ensure it is executed on the UI thread. If we are already on the UI thread the method is just called without Invoke.

By structuring the control update methods this way they can be called from any thread and will never throw an error due to cross thread calls.

Return top