Friday, December 19, 2008

Out for Christmas Break

Well, I'll be gone for a while for Christmas Break. When I come back, I'll have a wonderful series about Exceptions. I'll go through specific exceptions and describe what causes them, and what you can do to debug them. But for now, I'll leave you with some programmer's Christmas Carols:

If Programming Languages Were Christmas Carols

Thursday, December 18, 2008

Linq Subqueries

It's a rather simple problem, but a little difficult to figure out at first with Linq. The problem of subquerying. Let's say I have a FamilyMember class, that I've defined like this:

public class FamilyMember
{
public FamilyMember(string name)
{
Name = name;
}
public string Name { get; private set; }
}


Now, let's say that I've defined a Family class like this:

public class Family
{
public Family(string state, FamilyMember husband, FamilyMember wife)
{
State = state;
Members = new List<FamilyMember>();
Members.Add(husband);
Members.Add(wife);
}

public Family(string state, FamilyMember husband, FamilyMember wife, params FamilyMember[] children) :
this(state, husband, wife)
{
Members.AddRange(children);
}

public string State { get; private set; }

public List<FamilyMember> Members { get; private set; }
}


Now, let's say I add a whole bunch of families to a list:

// Create the family members.
FamilyMember glenn = new FamilyMember("Glenn");
FamilyMember debi = new FamilyMember("Debi");

FamilyMember daniel = new FamilyMember("Daniel");
FamilyMember amanda = new FamilyMember("Amanda");
FamilyMember rachel = new FamilyMember("Rachel");
FamilyMember joshua = new FamilyMember("Joshua");

FamilyMember matthew = new FamilyMember("Matthew");
FamilyMember shannon = new FamilyMember("Shannon");
FamilyMember elizabeth = new FamilyMember("Elizabeth");
FamilyMember abigail = new FamilyMember("Abigail");

FamilyMember david = new FamilyMember("David");
FamilyMember jennifer = new FamilyMember("Jennifer");

// Create the families.
Family springMortons = new Family("TX", glenn, debi);
Family bostonMortons = new Family("MA", daniel, amanda, rachel, joshua);
Family aggieMortons = new Family("TX", matthew, shannon, elizabeth, abigail);
Family houstonMortons = new Family("TX", david, jennifer);

// Make a list of all the families
List<Family> allFamilies = new List<Family>()
{ springMortons, bostonMortons, aggieMortons, houstonMortons };


Now that I have this list, I want to pull out all of the family members located in texas whose names begin with "D". How would I do this? It seems that Linq allows for nested subqueries, and they're rather simple to use once you get the hang of it. Here's the answer:

var dPeople = from family in allFamilies
where family.State == "TX"
from member in family.Members
where member.Name.StartsWith("D")
select member;


That's it! It's as simple as making two nested from statements. The first from statement will select the families, and the second will select the individuals within the families. The where clause immediately below the family selection will filter the families, and the where clause immediately below the member selection will filter the members. The resulting dPeople is an IEnumerable<FamilyMember>, and you can easily iterate through it to access each instance.

Happy coding!

Wednesday, December 17, 2008

Resetting Default Values in the Visual Studio IDE

Resetting default values in the Visual Studio IDE is simple. Simply, right click on any property whose default value is not set, and choose "Reset" from the associated context menu. This is a lifesaver when you really want to remove an icon from a form, and it can save you a trip to the designer.cs.




Tuesday, December 16, 2008

The Joys of the Path Class

I'm beginning to think that the Path class is sadly one of the most overlooked classes out there. I've seen plenty of good developers coming up with all sorts of crazy string parsing code to split apart filenames, when the Path class is quietly sitting alone, with no friends. Because I want the Path class to be social and have as many friends as its brothers, FileInfo and DirectoryInfo, allow me to introduce you to a few of the Path class's methods:
  • Path.GetDirectoryName - Takes a string parameter, and returns a string representing only the directory name of the file. Say goodbye to filename.Substring(0, filename.LastIndexOf(@"\")), and say hello to this method.
  • Path.GetFileName - How many of you have found yourself typing string filename = path.Substring(filename.LastIndexOf(@"\") + 1); when you could have just been using this method, which nicely extracts the filename out of the whole path for you?
  • Path.GetFileNameWithoutExtension - Oh, this is a nice one. If given the string "C:\Program Files\CompanyName\Filename.txt", Path.GetFileNameWithoutExtension will return simply "Filename".
  • Path.GetTempPath - Returns a string containing the full path to the system's temporary folder.
  • Path.ChangeExtension - Will change the extension of any filename in a path, and return to you the new full path.
  • Path.Combine - One of my favorites, this will allow me to take a string like "C:\Program Files\CompanyName" and another string like "Filename.txt", and easy get "C:\Program Files\CompanyName\Filename.txt".

Again, this is sadly overlooked by many developers, but it's there, so use it when you need to.

Monday, December 15, 2008

How Your Memory Affects Code Understanding

In a 1956 article by Psychologist George Miller it was determined that the short term memory of a human being is limited to (roughly) 7 "bits" of information at a time. Beyond this, the long term memory has to kick in.

I've started thinking about this in terms of how I refactor my code. Let's say I have a piece of code that looks like this:

Console.WriteLine(string.Format("Hello {0}, {1} has called you {2} time{3} today", 

   callee.FirstName, caller.FirstName, callcount, (callcount == 1 ? "" : "s")));


While this one line describes exactly what I want to do, it's incredibly confusing and requires me to spend alot of time analyzing it to understand the purpose. While short, it's relatively unreadable, and takes a good deal of time to comprehend.

Miller also talks of how combining bits of information together with each other can help memory retention. He calls these groups of bits chunks, and states that a chunk is about as difficult to remember as a bit. This means that the average programmer can remember, in short term memory, approximately 7 items, which could be bits or chunks.

How does this apply to your code? The code I posted above is one long line. The average reader is going to read code in bits, and then mentally group those pieces of code together to create one coherent whole. This process is made more difficult when the number of bits in the code exceed the number of bits that the human mind can remember mentally. When the user then has to analyze the text to find ways to chunk the information, this can drastically slow the process of reading code. In fact, the very act of analyzing the code will take a slot or two of this short term 7-item maximum, and will replace what's already there. Here's an example of how one developer might mentally separate the bits of data in their mind:

Console.WriteLine ... string.Format ... "Hello {0}, {1} has called you {2} time ... 

    {3} ...  today" ... callee ... FirstName ... caller ... FirstName ...

    callcount ... callcount == 1 ... ? ... "" ... : ... "s"


This is too many bits of information for the average person to remember in short term memory without chunking. So the reader would then be forced to reread the code in order to chunk the bits of information, so that he or she can better understand the code. The reader may have to make multiple passes to chunk the data mentally, and this can take significant time. The reader will have to focus on a small portion of the text, group that portion, and then move to a larger portion, and group that portion, and finally put it all together. This can take significant time, and can all but destroy efficiency in code review. Here's how our reader might chunk the information:

Console.WriteLine ... string.Format ... "Hello {0}, {1} has called you {2} time ... 

    {3} today" ... callee.FirstName ... caller.FirstName ...

    callcount ... (callcount == 1 ?  "" : "s")


Now the reader has 8 distinct chunks. This is somewhat manageable on a good day (says Miller). If I'm really tired, I might have to chunk it again:

Console.WriteLine(string.Format("Hello {0}, {1} has called you {2} time{3} today" ... 

    callee.FirstName ... caller.FirstName ...

    callcount ... (callcount == 1 ?  "" : "s")


Now I've gotten the chunks of code down to 5 chunks, but it took me two passes to get there. Compare the code above to the following code:
Now the question is, would it be easier for the reader of your code to group your code in their own mind, or would it be easier for you to chunk the code for them, by setting some local variables, causing the developer to read your code in small bits. Compare the code I first posted with the following:

string helloMessage = "Hello {0}, {1} has called you {2} {3} today";

 

string timeText = "time";

if (callcount != 1)

    timeText = "times";

 

string displayText = string.Format(helloMessage , 

    callee.FirstName, caller.FirstName, callcount, timeText);

 

Console.WriteLine(displayText);


Now, while this code may be significantly longer than the original code, and while small shortcuts could be taken without significantly affecting the speed of comprehension for the code, the above code groups for the reader. It makes the comprehension of the code somewhat simpler. Also, note that I've respected the natural chunking of the words "times" and "time". I haven't separated "time" from it's plural specifier. Splitting the word would create two bits of information from one bit of information that would need to be rejoined mentally before understanding the code fully. Finally, notice that I've indented a line when declaring the displayText variable. The reason for this is that the indentation creates a natural break mentally for the reader. It makes it simpler for the developer to chunk the data, and the indentation is placed functionally at a logical location. (The top line pertains to the format string, and the bottom line pertains to the objects to be inserted into the format string.)

In conclusion, while the one-line version of the code is less verbose and has fewer lines than the later version, it has to be grouped and chunked to be understood. Doing so can easily lead into fatigue or misunderstanding of the code. It's also harder to debug. So, in general, it's a better idea to write your code like you're writing it to a five year old, than to conglomerate and nest code statements ad infinitum in an attempt to "shorten" your code.

On a side note, you can naturally avoid many of the pitfalls of long one-line statements by setting a larger font in your IDE and reducing the amount of horizontal space available in your editor window. Doing this will cause you to naturally desire shorter, more easily digested, code statements.

Friday, December 12, 2008

Understanding Lambda Expressions

C# 3.0 introduced a new feature called lambda expressions. Using this syntax, you can shorten your code immensely, however, if you've never seen it before, it can be extremely confusing. I'm going to do my best in this post to explain how they work, but first, it's important to lay the groundwork. In that spirit, let's have a history lesson...

C# 1.0: Delegates and Methods

Delegates are essentially placeholders for methods. They define incoming and outgoing parameter types to create a specific signature for a method. They can be constructed, and in their constructor, you would pass in a pointer to a method whose signature matches the signature of the delegate. For instance, take the following delegate as an example:

public delegate int GetLengthDelegate(string value);


This delegate could be constructed just as any class instance can be constructed. Let's say you have the following method:

public int GetLength(string value)

{

    return value.Length;

}


Now, I can do the following:

public void RunDelegate()

{

    GetLengthDelegate getLength = new GetLengthDelegate(this.GetLength);

    Console.WriteLine(this.GetLength("Hello World!"));

    Console.WriteLine(getLength("Hello World!"));

}


In the code above, I'm first calling GetLength without using a delegate, and then I'm calling the very same method via the use of a delegate. In both situations, I'm getting the same result, because I'm passing in the same value.

The joy of delegates, is that they can be passed into a method. Let's say I added this code:

public void PrintLengths(GetLengthDelegate del)

{

    del("Hello World!");

}


And then I changed my RunDelegate method to look like this:

public void RunDelegate()

{

    GetLengthDelegate getLength = new GetLengthDelegate(this.GetLength);

    PrintLengths(getLength);

}


Now, I'm creating a delegate called getLength that points to the method this.GetLength, and then I'm passing it into another method, called PrintLengths, which will then call the delegate.

Delegates can be combined with each other, meaning that you could set up a delegate so that when you call del("Hello World"), you could trigger off several methods, which would be called one after another. This is called combining delegates, and it's a little out of scope for our topic.

In any case, all the syntax you see above is old, and has been around since the inception of C# 1.0.

C# 2.0: Anonymous Delegates

C# 2.0 introduced anonymous methods. This enabled programmers to write methods anonymously, without actually naming the method. These anonymous methods were used to pass into the constructors of delegates, in order to allow methods that take delegates as parameters call delegates that might be too short or too simple to really merit being programmed in as a member of the class. Anonymous delegates had the following syntax:

delegate(string value) { return value.Length; }


The first thing you'll notice here is a lack of definition for the return value. This is because the C# compiler would infer the type of the return value, based on the return values coded into the delegate.

The second thing you might notice is the use of the word delegate. Yes, the C# team decided that the term delegate can be used in two contexts. Used in one context delegate defines a delegate type, and in another context it defines an anonymous method. I personally feel they could have named it something else to be less confusing, but it is what it is.

The last thing you should notice about the anonymous method above, is that it has the exact same functionality as the GetLength method. In fact, I can actually use this anonymous method in the constructor to the GetLengthDelegate. This means that I could change my RunDelegate method to this:

public void RunDelegate()

{

    GetLengthDelegate getLength =

         new GetLengthDelegate(delegate(string value) { return Value.Length; } );    PrintLengths(getLength);

}


In fact, I could even go further and declare it without explicitly calling the GetLengthDelegate constructor, nor storing the instance of the delegate in the local getLength variable.

public void RunDelegate()

{

     PrintLengths(delegate(string value) { return value.Length; });

}


As you can see, the anonymous method syntax was a great improvement over the previous way of doing things, where an actual method had to be declared.

One caveat, however, anonymous methods cannot be declared without a context. That is, you can't just type a anonymous method into another method and expect it to work. They're designed to be assigned to delegates, not called straight out.

C# 3.0: Lambda Expressions

In C# 3.0, lambda expressions were introduced. Lambda expressions are nothing but syntactical sugar built upon anonymous methods. Our hero, the GetLength method, would look like this in an anonymous method:

s => s.Length


That's it. Just like the anonymous methods, however, they need to be assigned to a delegate. Thus, you could do this to create the same method as we've had above:

GetLengthDelegate getLength = s => s.Length;


Now, your first question is going to be obvious: "What is s?" Let me put it this way, I could have also written the above line as follows:

GetLengthDelegate getLength = value => value.Length;


Do you see it now? s and value actually refer to the string parameter sent into the lambda expression. We know that this is a string parameter, because we're assigning this lambda expression to the delegate GetLengthDelegate, which expects an incoming string parameter. Therefore, the C# compiler infers the type not only of the return value, but also of the incoming parameter.

What's more, the return keyword is conspicuously absent from the lambda expression. The C# compiler is smart enough to know that the value created on the right side of the => symbol is the return value of the delegate.

So, to put it briefly, the value on the left side of the => is the incoming parameter, and the value on the right is the outgoing parameter.

Putting It All Together

In .NET 3.5, LINQ was introduced. LINQ methods allow a user to filter, search, and do all sorts of other funky things to collections of items simply by providing a set of extension methods that accept delegates. For instance, there's the Where method, which takes a delegate of type Func. Now, what is Func? Basically, it's a generic delegate whose second parameter has been defined, but the first has not been. The actual definition of Func is the following:

public delegate TResult Func<t,>(T arg);


So it's a generic delegate. This means, that declaring it as a Func would mean that you're passing in a string as the incoming parameter, and expecting a bool as the return parameter. What does this mean for the Where method?

Well, basically, the Where's return type is IEnumerable<T>, where T refers to the generic type parameter that fills in the collection off of which you call the method. So, if you have a List<string>, the return of calling Where will return an IEnumerable<string> and you should pass in a method with the same signature as Func<string>. If you have a List<int>, the return parameter will be IEnumerable<int>, and you should pass in method with the same signature as Func<int>. The Where method will call the delegate you pass in to it for every object contained in your enumerable, and will return an IEnumerable<T> that contains all the objects for which this method returns true. Maybe an example will help:

List<string> list = new List<string>();

 

list.Add("David");

list.Add("Bob");

list.Add("Michael");

 

foreach (string name in list.Where(s => s.Length == 5))

    Console.WriteLine(name);


In the example above, I'm creating a list, and populating it out with three names. "David", "Bob" and "Michael". I'm then creating an IEnumerable<T> (in this case, an IEnumerable<string> containing only the names that are 5 characters long. In my example, that would only be "David", but if I had added "Jimmy" to the list, that would also be returned. The Where method will go through each of the items in list and evaluate the lambda expression I passed into the Where statement. In other words, it will call that method on each of the items in list. The if the return of the call to the lambda expression is true, the Where method will return that value as part of it's result, thus filtering the list to include only the string values that are 5 characters long.

I hope this explanation has been enlightening if you've been wondering what lambda expressions are. There is a bit more information on lambda expressions on the MSDN Library, as well as some generally out on the internet. Nevertheless, there's no replacement to learning the C# language, other than to code in it, so pull out your Visual Studio, load up a list, and give it a go. I think you'll find that these expressions can save you alot of time, and simplify your code greatly.

Thursday, December 11, 2008

On Return Values and Readability

Recently, I’ve been doing a lot of refactoring, and the importance of variable names has been re-impressed on my mind. Even in relatively clean code, changing the names of variables can improve things dramatically. Let’s start with the common return variable named result. The following is some relatively easy to understand code that can be altered to improve readability.

public Person GetPersonById(int id)

{

    if (id < 0)

        throw new ArgumentException("Id cannot be less than 0");

 

    Person result = null;

 

    using (SqlConnection cn = new SqlConnection(Config.SqlConnectionString))

    {

        cn.Open();

        using (SqlCommand cm = cn.CreateCommand())

        {

            cm.CommandText = "Person_GetById";

            cm.CommandType = CommandType.StoredProcedure;

            using (SqlDataReader dr = cm.ExecuteReader())

            {

            if (dr.Read())

                {

                    result = new Person();

                    result.Id = dr.GetInt32(dr.GetOrdinal("Id"));

                    result.FirstName = dr.GetString(dr.GetOrdinal("FirstName"));

                    result.LastName = dr.GetString(dr.GetOrdinal("LastName"));

                }

            }

        }

    }

 

    return result;

}


Now, maybe you think I’m picking a little bit too much, but I don’t like the variable result here. It’s not that result isn’t descriptive (we obviously know throughout the code that result is going to be returned from the method), it’s that it causes a simple readability issue that could be changed. Take the last line for instance:

return result;


Although this line is straightforward and simple, it tells me absolutely nothing in and of itself about the type of result that I’m returning. In order to get that, I either have to look up a few lines at the return type of the method, or I have to look at the declaration of the variable earlier on in the code. While that doesn’t seem like a whole lot to ask of your fellow developers who are reading your code after you, using result isn’t doing them any favor when they have literally hundreds of methods that end this exact same way. Simply changing this variable name can make that single line more readable. Which looks better, the above return statement, or the following:

return person;


Obviously, the second is more descriptive. In one statement, it’s clear I’m returning a person. It’s true that I could have looked at the method declaration at the top to determine that I will be returning a person, however, that’s going to add another split second of brain power (and perhaps mouse scrolling) to glance back up to the top of the method. Multiply this several times for each method, and you'll quickly have a difficult-to-skim code base.

This leads me to my next complaint about the naming conventions in this code. There are three variables in named cn, cm, and dr respectively, and they’re all acronyms. I hate acronyms with a passion, unless they’re very well-known acronyms to the rest of the world. There’s a difference between using SQL and using cn. SQL is well-known, whereas cn is proprietary to my own mind. I might have always used cn, but another developer may not. This is not an accepted standard. Never assume that other people use the same variable naming standards and habits as you. This needs to be named something more descriptive, such as sqlConnection.

Before I show you my final code, I should tell you I decided to make one more change in the way the code is laid out. I separated the retrieval of the column ordinal numbers from the code that fetches the value of the columns. There’s two reasons for this. The first is (of course) readability. It’s easier to visually understand one line that gets the ordinal number for a column, than it is to understand one line that does that and fetches the value at the same time.

The final version looks like this:

public Person GetPersonById(int id)

{

    if (id < 0)

        throw new ArgumentException("Id cannot be less than 0");

 

    Person person = null;

 

    using (SqlConnection sqlConnection = new SqlConnection(Config.SqlConnectionString))

    {

        sqlConnection.Open();

 

        using (SqlCommand sqlCommand = sqlConnection.CreateCommand())

        {

            sqlCommand.CommandText = "Person_GetById";

            sqlCommand.CommandType = CommandType.StoredProcedure;

 

            using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader())

            {

                int idColumn = sqlDataReader.GetOrdinal("Id");

                int firstNameColumn = sqlDataReader.GetOrdinal("FirstName");

                int lastNameColumn = sqlDataReader.GetOrdinal("LastName");

 

                if (sqlDataReader.Read())

                {

                    person = new Person();

                    person.Id = sqlDataReader.GetInt32(idColumn);

                    person.FirstName = sqlDataReader.GetString(firstNameColumn);

                    person.LastName = sqlDataReader.GetString(lastNameColumn);

                }

            }

        }

    }

 

    return person;

}


Now, you may disagree with this approach. However, I believe the major advantage here is that every single line can be easily understood as a unit all to itself. I could feed the average developer any one line out of this whole block of code, and he should be able to tell me exactly what the line is doing. This makes for easy skimming and easy understandability.

Hopefully, in reading this, you’ve come to the same conclusion that I have. Naming your variables properly is of utmost importance. Here’s a couple of rules to keep in mind:

1. Don’t use result (or any of it’s variants such as rtn, returnValue, or ret. Even if the result value is a primitive type, the value should stand for something. Name your return values based on what they stand for in the business world. C# is an object-oriented language. Think in objects, and name your parameters, including your return value, appropriately.

2. Read your code aloud. Does it make sense when you read it aloud? If not, you could probably change something to make it more readable.

3. Move outside of “this-week-thinking”. We developers tend to get caught up in what we’re doing right now without concern for the future. In the excited frenzy of creativity and laying out new code, we can often forget that we’re going to have to read our own code sometime in the future, after we forget what we originally wrote. Try to remove yourself from the current situation and read the method as though you’ve never seen it before. Does it describe itself? If not, do the refactoring immediately after writing the method.

Over the next few posts, I hope to be writing more about clean code production and refactoring. I hope they help.

Friday, December 5, 2008

Something Every .NET Developer Should Do Today

Ever heard of the Microsoft Shared Source Initiative? If not, you need to check it out. Microsoft has released the source code for several of the .NET Base Class Libraries, plus some that aren't in the BCL. With the Shared Source Initiative, you can access .NET source code directly from the debugger in VS2008. Visit the link above for more information, and how to set up source code access from Visual Studio 2008. It takes all of 5 minutes, and might save you tons of headaches in the future.

Wednesday, November 19, 2008

Using WebBrowser To Edit Web Pages On The Fly

The WebBrowser control is more versatile than you might think it is. It can be used to alter the look and feel of specific pages, click buttons, and add text to input boxes. Here's a good example.

1. Create a new Windows Form and add a WebBrowser control to it.
2. Create and attach an event handler to the DocumentCompleted event of the WebBrowser control. Make the event handler look like this.


bool _finished = false;

 

void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

{

    if (!_finished)

    {

        HtmlElement qInput = webBrowser1.Document.GetElementsByTagName("INPUT").OfType<HtmlElement>().Where(el => el.Name == "q").FirstOrDefault();

        if (qInput != null)

        {

            qInput.SetAttribute("value", "Hello World!");

        }

 

        HtmlElement qButtonSearch = webBrowser1.Document.GetElementsByTagName("INPUT").OfType<HtmlElement>().Where(el => el.Name == "btnG").FirstOrDefault();

        if (qButtonSearch != null)

        {

            qButtonSearch.InvokeMember("click");

        }

        _finished = true;

    }

}



Now run the application. The result I received was this:



Let's walk through the code briefly:

The key lines in here are within the if statement that wraps the entire method code. First, I fetch all the elements with the tag name of INPUT, and I select only the tag named "q", which is the name of the element on the web page. The SetAttribute method will allow you to set the DOM attribute of any element in the HTML page. Knowing this, I can simply set the "value" attribute of the input to have the effect of filling in the textbox. In my example, I fill the textbox with the text "Hello World!".

The next small block uses the same general concept to find the Search button on the page, and then it calls "InvokeMember" to invoke the event attached to the control. In this situation above, I want to invoke the "click" event, so I pass the "click" string into the InvokeMember method, which kicks off the search, and ultimately redirects me to another page.

A brief warning:

Not all pages load all of their HTML at once. Some pages load in stages. This can have the effect of making some of your elements unavailable at DocumentCompleted. It may be necessary in this situation this to have some kind of Timer whose tick event kicks off the HTML actions you want to perform. Then, you can wrap all the actions in a try/catch, and stop the timer once the actions execute successfully.

This same general concept can also be used to set style on elements (try setting Style to "DISPLAY:none;" on an element, and see what happens.)

Friday, November 7, 2008

C# 4.0 Features Announced!

So, I'm a little behind the eight-ball on this one (this was released about two weeks ago), but the C# 4.0 team has released a whitepaper detailing the planned features for C# 4.0 including the new "dynamic" type, optional parameters, variance for suitable interfaces and types, as well as the new "in" and "out" modifiers for generic type parameters, allowing for covariance and contravariance. They've posted this information here!

Give it a look!

Wednesday, November 5, 2008

An Event Monitor Class



I recently received a question on the forums regarding the creation of an anonymous event handler method. Pretty much every event in the .NET Framework employs the same signature, with slight variations. According to the EventHandler page on MSDN, the standard signature for an event handler is a method that returns void, takes object as the first parameter, and takes a type that has been derived from EventArgs as it's second parameter. Microsoft has adhered to this rule with excellent consistency. Because of this, the ability to attach to every single event within a specific class is not too terribly difficult to do.

Nevertheless, I've found that at times, I've wanted to know which event is actually being raised. Perhaps I want to handle all the events in a single method, but I want to know for certain the name of the event raised on the object to which I'm subscribing. This is what I've created below.

First, I created an AnonymousEventArgs class, which itself derives from EventArgs, and contains two properties: EventName, which carries the name of the event raised, and InnerEventArgs, which contains the original EventArgs value that was created when the event was raised. It looks like this:


public class AnonymousEventArgs : EventArgs
{
public AnonymousEventArgs(string eventName, EventArgs innerEventArgs)
{
EventName = eventName;
InnerEventArgs = innerEventArgs;
}

public EventArgs InnerEventArgs { get; private set; }

public string EventName { get; private set; }
}
Next, I created a single class called "EventMonitor". EventMonitor has, at it's heart, a class called "AnonymousEventHandlerContainer" This class is designed as a generic class, with a type parameter that must inherit from EventArgs. This type parameter is used as the second parameter of the "Handler" method, which is the event handler for the specific event it is subscribed to. Each event on the object passed in as the sender in the EventMonitor will have one AnonymousEventHandlerContainer created for it, and that object will subscribe to only one event per instance. It is a nested class, and it looks like this:


public class AnonymousEventHandlerContainer<eventargs> where eventargs : EventArgs
{
// This is the name of the event subscribed to.
public string EventName { get; private set; }

// This references the parent EventHandler.
public EventMonitor Parent { get; private set; }

public AnonymousEventHandlerContainer(EventMonitor parent, string eventName)
{
EventName = eventName;
Parent = parent;
}

// This the generic handler that is used to subscribe to the object.
public void Handler(object sender, eventargs e)
{
if (Parent != null && Parent.Event != null)
Parent.Event(sender, new AnonymousEventArgs(EventName, e));
}
}
The EventMonitor is constructed by passing in the object whose methods you wish to subscribe to. It contains four methods, two of which subscribe or unsubscribe to specific events and two that subscribe to all the events on the object.

In addition to this, EventMonitor contains one event of type EventHandler<AnonymousEventArgs>, which is used for the creating class to subscribe to all events in the passed in object. The entire class looks like this:

public class EventMonitor
{
public EventMonitor(object sender)
{
Sender = sender;
}

public event EventHandler<AnonymousEventArgs> Event;

public object Sender { get; private set; }

private Dictionary<string, Delegate> eventHandlers = new Dictionary<string, Delegate>();

private int EventCount
{
get
{
return eventHandlers.Count;
}
}

/// <summary>
/// Subscribes to every event on the Sender.
/// </summary>
public void AttachAllEvents()
{
Sender.GetType().GetEvents().ToList().ForEach(e => AttachEvent(e.Name));
}

/// <summary>
/// Unsubscribes from every event on the Sender.
/// </summary>
public void DetachAllEvents()
{
Sender.GetType().GetEvents().ToList().ForEach(e => DetachEvent(e.Name));
}

/// <summary>
/// Stops monitoring a specific event.
/// </summary>
/// <param name="eventName">The name of the event to stop subscribing to. </param>
public void DetachEvent(string eventName)
{
if (eventHandlers.ContainsKey(eventName))
{
// Get the event information for the specified event.
EventInfo eventInfo = Sender.GetType().GetEvent(eventName);

if (eventInfo != null)
{
// Unsubscribe from the event.
eventInfo.RemoveEventHandler(Sender, eventHandlers[eventName]);

// Remove the handler method from the list of handler methods.
eventHandlers.Remove(eventName);

}
}
}

/// <summary>
/// Adds a generic event handler to any event whose type subscribes to the standard
/// event handler signature. (First parameter: object, second parameter inherits
/// from EventArgs).
/// </summary>
/// <param name="eventName">The name of the event to subscribe to.</param>
public void AttachEvent(string eventName)
{
// Don't subscribe twice.
if (!eventHandlers.ContainsKey(eventName))
{

// Get the event information for the specified event.
EventInfo eventInfo = Sender.GetType().GetEvent(eventName);

if (eventInfo != null)
{

// Get the handler type for the specified event.
Type handlerType = eventInfo.EventHandlerType;

// Get the ParameterInfo collection for the event handler's invoke method.
ParameterInfo[] parameterInfos = handlerType.GetMethod("Invoke").GetParameters();

// Get the collection of types corresponding to the event handler's parameters.
Type[] parameterTypes = parameterInfos.Select(p => p.ParameterType).ToArray();

// Only attach a handler to methods that conform to the standard event handler signature
// of two parameters, one being an object sender, and the second being derived from
// eventargs.
if (parameterTypes.Length == 2 && parameterTypes[0] == typeof(object) &&
typeof(EventArgs).IsAssignableFrom(parameterTypes[1]))
{
// Create an array of generic type parameters.
Type[] genericTypeParameters = new Type[] { parameterTypes[1] };

// Get the type of the AnonymousDelegateClass, and fill the generic parameters.
Type type = typeof(AnonymousEventHandlerContainer<>).MakeGenericType(genericTypeParameters);

Type[] constructorTypes = new Type[] { typeof(EventMonitor), typeof(string) };

// Get the constructor for the class that takes the string value.
ConstructorInfo constructor = type.GetConstructor(constructorTypes);

// Create an instance of the class, which will subscribe to the event specified.
object instance = constructor.Invoke(new object[] { this, eventName });

// Get the Handler method, which will be the event handler for the event.
MethodInfo method = type.GetMethod("Handler");

// Create a delegate of the same type of the handler type based on the Handler method.
Delegate eventhandler = Delegate.CreateDelegate(handlerType, instance, method);

// Add the event handler to the object specified.
eventInfo.AddEventHandler(Sender, eventhandler);

// Finally, record the method subscriber in case we need to remove it.
eventHandlers.Add(eventName, eventhandler);
}
}
}
}


public class AnonymousEventHandlerContainer<eventargs> where eventargs : EventArgs
{
// This is the name of the event subscribed to.
public string EventName { get; private set; }

// This references the parent EventHandler.
public EventMonitor Parent { get; private set; }

public AnonymousEventHandlerContainer(EventMonitor parent, string eventName)
{
EventName = eventName;
Parent = parent;
}

// This the generic handler that is used to subscribe to the object.
public void Handler(object sender, eventargs e)
{
if (Parent != null && Parent.Event != null)
Parent.Event(sender, new AnonymousEventArgs(EventName, e));
}
}
}

Now, how to use the class. I tested this class by creating a new Windows Forms application, adding a single RichTextBox called "richTextBox1" and adding a DateTimePicker called "dateTimePicker1" onto the form. I then attached the DateTimePicker to the EventMonitor class. My form looked like this:

public partial class Form1 : Form
{
EventMonitor monitor;

public Form1()
{
InitializeComponent();
monitor = new EventMonitor(dateTimePicker1);
monitor.AttachAllEvents();
monitor.Event +=
new EventHandler<AnonymousEventArgs>(monitor_Event);

}

void monitor_Event(object sender, AnonymousEventArgs e)
{
richTextBox1.AppendText(string.Format("{0}: {1}{2}",
DateTime.Now.ToShortTimeString(),
e.EventName,
Environment.NewLine));
}
}
If you run this application, you'll notice output from every event that is raised on the DateTimePicker. The event name is displayed in the RichTextBox, along with the time it was raised.

I have found this class to be helpful in determining which events are raised, whether events are raised, and in what order they're raised.

Wednesday, October 29, 2008

Really Strange C# Scope Syntax

Did you know you can define a separate variable scope within a C# method? I'm not sure why you would ever want to use this syntax, but it's there if you want it. Simply open a set of squiggly brackets within your method, and define variables within the brackets. The variables will be out of scope when you leave the brackets. Thus, the following code compiles just fine:


public void Run()

{

    int value = 0;

 

    {

        int innervalue = 2;

        Console.WriteLine(innervalue);

    }

 

    {

        string innervalue = "string";

        Console.WriteLine(innervalue);

    }

 

    Console.WriteLine(value);

}

It's important to note that there's nothing especially different about how the C# compiler compiles this code. The declared variables aren't popped from the stack until the method leaves, and nothing unusual happens to them during the execution of the method. All of these values remain on the stack (or the heap) until the method returns. In fact, in the example above, the compiler actually renames the second "innervalue" local variable as "V_2", and references it that way in the IL. So this is just a feature of the language.

Nevertheless, it's a fun trick to show your friends at all your coding parties.

This just goes to show that scope is as simple as knowing that any variables declared within squiggly brackets in C# are unavailable outside the squiggly brackets.

Tuesday, October 21, 2008

Extension Methods Don't Throw NullReferenceException!

Did you know that an extension method will not throw a NullReferenceException unless you explicitly tell it to? Because an extension method is technically not part of an instance of an object, they won't throw NullReferenceExceptions when the value from which they're called is null. Here's an example:


class ExtensionMethodTest

{

    public void Run()

    {

        string value = null;

        value = value.IfNull("Other");

        Console.WriteLine(value);

    }

}

 

static class StringExtensions

{

    public static string IfNull(this string value, string alternate)

    {

        if (String.IsNullOrEmpty(value))

            return alternate;

        return value;

    }

}


Add this to your code and call the Run() method. You'll notice that even though the variable value is null, it won't throw a NullReferenceException at runtime.

Wednesday, October 8, 2008

Ajax calls, Internet Explorer, and Caching

Tip of the day: Internet explorer caches HTTP GET requests when called through AJAX.

Now, why does this apply to you?

The reason this is important is in situations where you rapidly call an HTTP GET method from javascript. If you make the calls too rapidly in succession, you'll get the same information from each call, regardless of the .NET implementation of your web service. In fact, if you call them too quickly in succession, IE doesn't even make the call to the web service, but instead returns the cached data.

Let's say you have a web method called "GetNewRandom()". (This is definately an ironic name, given that calls to the Random class repeats the same values when called in rapid-fire succession.) Now, let's say you've decorated your GetNewRandom class like this:



[WebMethod(true)]

[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]

public Int32 GetNewRandom()

{

    Byte[] bytes = new Byte[4];

    new System.Security.Cryptography.RNGCryptoServiceProvider().GetBytes(bytes);

    return BitConverter.ToInt32(bytes, 0);

}



Now, let's say you need to call this repeatedly over and over again quickly. Apparently, since the header for this call is identical each time you call it, Internet Explorer will actually cache the value on the client, assuming that the data that will be returned will be the same as it was the time before, and you'll get the same value repeated, until IE deems the cached data worthy of deletion and refreshing. This can be extremely problematic.

The solution?

Set UseHttpGet to "false" if you absolutely, positively need new data every single time. IE doesn't cache the HTTP POST.

Tuesday, October 7, 2008

A Simple DocBrowser Control

I feel like giving away things for free today! Here's a simple DocBrowser user control that does nothing but display a Word Document in a WebBrowser Control. I've documented the code to enable you, my reader, to understand exactly what's going on. I encourage you to take this, use this, and enjoy it.

Make sure you add a reference to Microsoft.Office.Interop.Word in your project in order for this to work. I used the Office 2007 Libraries for this.


using System;
using System.Linq;
using System.Windows.Forms;
using Microsoft.Office.Interop.Word;
using System.IO;

namespace WordControls
{
public partial class DocBrowser : UserControl
{
private System.Windows.Forms.WebBrowser webBrowser1;

delegate void ConvertDocumentDelegate(string fileName);

public DocBrowser()
{
InitializeComponent();

// Create the webBrowser control on the UserControl.
// This code was moved from the designer for cut and paste
// ease.
webBrowser1 = new System.Windows.Forms.WebBrowser();

webBrowser1.Dock = System.Windows.Forms.DockStyle.Fill;
webBrowser1.Location = new System.Drawing.Point(0, 0);
webBrowser1.MinimumSize = new System.Drawing.Size(20, 20);
webBrowser1.Name = "webBrowser1";
webBrowser1.Size = new System.Drawing.Size(532, 514);
webBrowser1.TabIndex = 0;

Controls.Add(webBrowser1);

// set up an event handler to delete our temp file when we're done with it.
webBrowser1.DocumentCompleted += webBrowser1_DocumentCompleted;
}

string tempFileName = null;

public void LoadDocument(string fileName)
{
// Call ConvertDocument asynchronously.
ConvertDocumentDelegate del = new ConvertDocumentDelegate(ConvertDocument);

// Call DocumentConversionComplete when the method has completed.
del.BeginInvoke(fileName, DocumentConversionComplete, null);
}

void ConvertDocument(string fileName)
{
object m = System.Reflection.Missing.Value;
object oldFileName = (object)fileName;
object readOnly = (object)false;
ApplicationClass ac = null;

try
{
// First, create a new Microsoft.Office.Interop.Word.ApplicationClass.
ac = new ApplicationClass();

// Now we open the document.
Document doc = ac.Documents.Open(ref oldFileName, ref m, ref readOnly,
ref m, ref m, ref m, ref m, ref m, ref m, ref m,
ref m, ref m, ref m, ref m, ref m, ref m);

// Create a temp file to save the HTML file to.
tempFileName = GetTempFile("html");

// Cast these items to object. The methods we're calling
// only take object types in their method parameters.
object newFileName = (object)tempFileName;

// We will be saving this file as HTML format.
object fileType = (object)WdSaveFormat.wdFormatHTML;

// Save the file.
doc.SaveAs(ref newFileName, ref fileType,
ref m, ref m, ref m, ref m, ref m, ref m, ref m,
ref m, ref m, ref m, ref m, ref m, ref m, ref m);

}
finally
{
// Make sure we close the application class.
if (ac != null)
ac.Quit(ref readOnly, ref m, ref m);
}
}

void DocumentConversionComplete(IAsyncResult result)
{
// navigate to our temp file.
webBrowser1.Navigate(tempFileName);
}

void webBrowser1_DocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
if (tempFileName != string.Empty)
{
// delete the temp file we created.
File.Delete(tempFileName);

// set the tempFileName to an empty string.
tempFileName = string.Empty;
}
}

string GetTempFile(string extension)
{
// Uses the Combine, GetTempPath, ChangeExtension,
// and GetRandomFile methods of Path to
// create a temp file of the extension we're looking for.
return Path.Combine(Path.GetTempPath(),
Path.ChangeExtension(Path.GetRandomFileName(), extension));
}
}
}

Here's a simple form I built with the control. The button's event handler simply calls LoadDocument on the DocBrowser control, which is the main portion of the screen. I opened some notes from when I was studying for the 70-536 exam.

Saturday, October 4, 2008

Changing Attribute Parameters at Runtime

A question was asked on the C# forums yesterday regarding how to set a field in a PropertyGrid to readonly during runtime. Just in case you're not familiar with the PropertyGrid in C#, it's the control you use to set items in the "Properties" window in Visual Studio. Unfortunately, the .NET implementation of this control for use in Windows Forms is pretty basic and doesn't provide much functionality in the way of setting certain fields to readonly, etc. Instead, it depends on the attributes applied to the object it's editing to determine it's behavior. For instance, to make a property reaonly within the PropertyGrid, the ReadOnlyAttribute needs to be applied to that property within the object the PropertyGrid is editing. This makes things a little more difficult from a runtime perspective, because attribute values cannot easily be set at runtime. Nevertheless, what follows are detailed instructions on how to do just that, and have the PropertyGrid update itself accordingly.

Follow along with my example:

1. Create a new Windows Forms project.

2. Add the following class to your project:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Reflection;
 
namespace WindowsFormsApplication1
{
public class Employee
{
string name;
bool isMarried;
string spouseName;
 
public string Name
{
get { return name; }
set { name = value; }
}
 
public bool IsMarried
{
get { return isMarried; }
set
{
isMarried = value;
 
// set the spouseName to empty if the employee is not married.
if (!value)
spouseName = string.Empty;
}
}
 
public string SpouseName
{
get { return spouseName; }
set { spouseName = value; }
}
}
}
3. Add a PropertyGrid to your form, leaving the default name of "propertyGrid1".

4. Add the following line to the form's constructor, just after the call to InitializeComponent():


propertyGrid1.SelectedObject = new Employee();
5. Run the project.

You should see a screen like this:



Add some text in the SpouseName field, and then double click on the IsMarried value a couple of times. Notice that when the IsMarried property is set to true, the SpouseName field is set to an empty string. This is because we're changing the value within our class to an empty string if the IsMarried property is false. We really don't want a spouse for the employee, if the employee isn't married. Here's the problem however: you could set the IsMarried field to false, and still have a SpouseName value, simply by setting the SpouseName field after setting the IsMarried value to false. Of course, this isn't what we want. It would be far more user friendly to simply disable that entire field, and prevent the user entirely from changing the SpouseName in the PropertyGrid.

Let's add the ReadOnlyAttribute to the SpouseName property in the object:


[ReadOnly(true)]
public string SpouseName
{
get { return spouseName; }
set { spouseName = value; }
}
Now, rerun the application. The form now looks like this:



Notice the SpouseName is readonly, but it's permanently readonly. That's not what we want either. We only want SpouseName to be readonly when IsMarried is set to false. So here's the solution. We need to manually change the ReadOnly value of this specific ReadOnlyAttribute at runtime. I grabbed a copy of Lutz's .NET Reflector and browsed the internal workings of the ReadOnlyAttribute class. I found that there's actually an internal field called "isReadOnly" that determines whether the ReadOnly property of the ReadOnlyAttribute is true or false. Using TypeDescriptor, PropertyDescriptor and Reflection, I can set this value at runtime, and then I can notify the PropertyGrid to refresh all the data.

Change your IsMarried property to this:


[RefreshProperties(RefreshProperties.All)]
public bool IsMarried
{
get { return isMarried; }
set
{
isMarried = value;
 
// set the spouseName to empty if the employee is not married.
if (!value)
spouseName = string.Empty;
 
// Create a PropertyDescriptor for "SpouseName" by calling the static GetProperties on TypeDescriptor.
PropertyDescriptor descriptor = TypeDescriptor.GetProperties(this.GetType())["SpouseName"];
 
// Fetch the ReadOnlyAttribute from the descriptor.
ReadOnlyAttribute attrib = (ReadOnlyAttribute)descriptor.Attributes[typeof(ReadOnlyAttribute)];
 
// Get the internal isReadOnly field from the ReadOnlyAttribute using reflection.
FieldInfo isReadOnly = attrib.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
 
// Using Reflection, set the internal isReadOnly field.
isReadOnly.SetValue(attrib, !value);
 
}
}
Now run your application again. You should notice now, that when you set the IsMarried property to false, the SpouseName becomes readonly, but when the IsMarried property is set to true, you can edit the field. There's two reasons for this:

1. We've added the RefreshPropertiesAttribute to the property. This ensures that the PropertyGrid is refreshed whenever that particular property is changed, forcing the PropertyGrid to reload all the property attributes on the object.

2. We've manually changed the ReadOnly property on the ReadOnly attribute of the SpouseName property to false within the setter for IsMarried. The PropertyGrid will reload this attribute now when refreshing itself.

There are several applications for this, the biggest of which being conditional readonly properties on certain user controls that can be designed within Visual Studio. Other applications could be for applications that want to use the built-in functionality of PropertyGrid to edit business objects at runtime.

Friday, September 26, 2008

Determining If a File Is Cut or Copied to the Clipboard

I received a question on the Microsoft Forums today regarding whether or not a file is cut or copied to the clipboard. Using the System.Windows.Forms.Clipboard class, we can retrieve the data that is on the Windows Clipboard, however, only a small subset of this information is exposed easily through the managed methods on the clipboard. Enter the IDataObject interface.

You can access an object implementing this interface from the Clipboard.GetData() static method. The resulting implementation can return you a list of Formats included in the clipboard. Using these format strings, you can retrieve all of the information on the Clipboard. For example, take the following code:



   1:  IDataObject d = Clipboard.GetDataObject();

   2:  foreach (string format in d.GetFormats())

   3:      Console.WriteLine("Format: {0},\n .NET Data Type {1}\n\n", format, d.GetData(format).GetType().FullName);

   4:  Console.ReadLine();



Right clicking on a file in Explorer and copying a file, and then running the code above gives me the following output in the console:

Format: Shell IDList Array,
.NET Data Type System.IO.MemoryStream


Format: FileDrop,
.NET Data Type System.String[]


Format: FileNameW,
.NET Data Type System.String[]


Format: FileName,
.NET Data Type System.String[]


Format: Preferred DropEffect,
.NET Data Type System.IO.MemoryStream


Format: Shell Object Offsets,
.NET Data Type System.IO.MemoryStream

Playing around with these values can give you some interesting results. For instance, the format "Preferred DropEffect" is actually a MemoryStream mapped to an integer value. Converting it from a MemoryStream to an Int32, you can determine if a file was cut or copied to the clipboard in explorer:



   1:  static DragDropEffects GetCurrentDropEffect()

   2:  {

   3:      string format = "Preferred DropEffect";

   4:   

   5:      Object obj = Clipboard.GetData(format);

   6:   

   7:      if (obj != null)

   8:      {

   9:          MemoryStream ms = (MemoryStream)obj;

  10:          BinaryReader br = new BinaryReader(ms);

  11:          return (DragDropEffects)br.ReadInt32();

  12:      }

  13:      return DragDropEffects.None;

  14:  }



Check it out for yourself. Here's a little console app to display the results:



   1:  [STAThread]

   2:  static void Main(string[] args)

   3:  {

   4:      Console.WriteLine("Perform a file operation.");

   5:      do

   6:      {

   7:          Console.Clear();

   8:          DragDropEffects currentEffect = GetCurrentDropEffect();

   9:          string cutOrCopy = "None";

  10:          switch (currentEffect)

  11:          {

  12:              case DragDropEffects.Copy | DragDropEffects.Link:

  13:                  cutOrCopy = "Copy";

  14:                  break;

  15:              case DragDropEffects.Move:

  16:                  cutOrCopy = "Cut";

  17:                  break;

  18:          }

  19:          Console.WriteLine("Last operation was: {0}", cutOrCopy);

  20:          Console.WriteLine("Perform a function and press enter or type \"exit\" to quit");

  21:      } while (Console.ReadLine() != "exit");

  22:  }



That's all I got for today!

Monday, September 22, 2008

Beware of the Settings Designer

Visual Studio 2008 and 2005 both provide a very simple method of creating default settings for an application. While there is a place for the settings designer, you should be aware of a couple of the "gotchas" that come along with the settings designer, so you don't make a serious security blunder.

.NET settings that are entered using the settings designer create two files: Settings.settings and Settings.designer.cs. Settings.settings is used for viewing the settings at design time, while Settings.Designer.cs is actually compiled into the DLL.

In the settings designer, it's possible to add a connection string by setting the type to "(Connection string)". I believe this is a mistake on the part of Microsoft. While it's extremely convenient to add a connection string via the Connection Properties window that can be used to specify the connection string, it has the added effect of luring unsuspecting developers into actually using it, despite the warning that pops up when you indicate to save the password (manually typing a connection string will not yield this warning), and then compiling the connection string into the DLL. Once the value of the connection string is entered into the settings designer, the IDE automatically updates the Settings.Designer.cs file, as well as the app.config, and it puts this connection string in both locations.

Creating a connection string in the settings designer yielded the following code in the Settings.Designer.cs file:

[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.ConnectionString)]
[global::System.Configuration.DefaultSettingValueAttribute("Data Source=localhost;Initial Catalog=myDatabase;User ID=myUserName;Password=myPa" +
"ssword;")]
public string MyConnectionString {
get {
return ((string)(this["MyConnectionString"]));
}
}


And this code is then compiled into the assembly, and available for viewing in any disassembler program. I was easily able to view my connection string in Reflector by opening the property in Reflector:

.property instance string MyConnectionString
{
.get instance string SecurityNightmare.Properties.Settings::get_MyConnectionString()
.custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor()
.custom instance void [System]System.Configuration.SpecialSettingAttribute::.ctor(valuetype [System]System.Configuration.SpecialSetting) = { int32(0) }
.custom instance void [System]System.Configuration.ApplicationScopedSettingAttribute::.ctor()
.custom instance void [System]System.Configuration.DefaultSettingValueAttribute::.ctor(string) = { string('Data Source=localhost;Initial Catalog=myDatabase;User ID=myUserName;Password=myPassword;') }
}


So, that being said, avoid adding connection strings within the settings.designer. It's much safer to add them manually to the app.config.

Thursday, August 28, 2008

Overriding ListBox's DefWndProc to Create a Gray Free Read-Only Control

Inside every Windows Forms control, there's a mysterious method called "DefWndProc". According to MSDN, this method "Sends the specified message to the default window procedure.". Here's how it works:

First, you click a button on your mouse, or press something on your keyboard. Windows processes your request, and sends your request, via the Message structure to a method called "WndProc". WndProc will process the message, and is responsible for raising the events you can attach to in your code, such as the OnMouseClick and OnKeyPress events. Before raising these events, it calls DefWndProc, for Windows to handle the default behavior on the control.

Handling the default behavior of the control includes doing things like painting a new character in a textbox, making a button look pressed when the user clicks it, drawing a check in a checkbox when the user clicks it, and highlighting and selecting items in a ListBox. The beauty of overriding DefWndProc is that, while the events of the control will still be raised and your custom actions will still be executed, you can still stop the default behavior from being executed.

One thing you should know before you start, however, is that the Message structure is not very user-friendly. The key to it, however, is the "Msg" property, which indicates the actual action that the user has performed. PInvoke.net has posted an enumeration including windows messages, and some of their descriptions so you can figure out which messages mean what. But the simplest (and in my opinion, most educational) way to learn these messages, however, is to insert a Debug.WriteLine in your overridden DefWndProc, and then watch the messages in Visual Studio's output window as you debug your application. You'll probably be surprised at the sheer number of messages that are sent from Windows to your control whenever you do anything relating to your control. Experimenting with blocking these messages in DefWndProc can give you great control over your control.

So, in the example below, I've extended the ListBox control to add a "ReadOnly" property, and also to block any messages from the UI that might affect my control from being selected. Essentially, this blocks the user out of the control selection process, while allowing the code to do the selecting and deselecting. It will allow the user to scroll through the ListBox (unlike the effect that setting Enabled to false has on the ListBox), and it will prevent the ForeColor from going gray.



   1:  using System.Windows.Forms;

   2:   

   3:  namespace CustomControls

   4:  {

   5:      public class ReadOnlyListBox : ListBox

   6:      {

   7:          private bool _readOnly = false;

   8:   

   9:          public bool ReadOnly

  10:          {

  11:              get { return _readOnly; }

  12:              set { _readOnly = value; }

  13:          }

  14:   

  15:          protected override void DefWndProc(ref Message m)

  16:          {

  17:              // If ReadOnly is set to true, then block any messages

  18:              // to the selection area from the mouse or keyboard.

  19:              // Let all other messages pass through to the

  20:              // Windows default implementation of DefWndProc.

  21:              if (!_readOnly

  22:                  ((m.Msg <= 0x0200 || m.Msg >= 0x020E)

  23:                  && (m.Msg <= 0x0100 || m.Msg >= 0x0109)

  24:                  && m.Msg != 0x2111

  25:                  && m.Msg != 0x87))

  26:              {

  27:                  base.DefWndProc(ref m);

  28:              }

  29:          }

  30:      }

  31:  }