Friday, September 5, 2008

TreeView node font problem

Recently I encountered the following problem. I needed to set the font style of some nodes in a treeview at runtime to bold; but after setting the NodeFont property of the node the font changed correctly, but the text of the node was cut off.

This screenshot shows the problem:


The solution to the problem is to add an empty string to the Text property after setting the NodeFont property:

this.treeView1.SelectedNode.NodeFont = new Font(this.treeView1.Font, FontStyle.Bold);
this.treeView1.SelectedNode.Text += string.Empty;


The problem is also known at Microsoft and I found this workaround here.

This screenshot shows the correct text:

Monday, June 16, 2008

Enhanced combobox with readonly and working value member

As I had several problems with the standard combo box of the .Net 2.0 Framework such as the missing read only property or the not working value member property (if not using a datasource), I decided to write my own improved combo box. To change the default combobox to my needs I overwrote the OnPaint() mehtod and provided some additional methods.

With the enhanced combo box you can finally specify a value member without having to use a datasource as you can see in the code below:
Customer customer1 = new Customer();
customer1.FirstName = "John";
customer1.ID = 1;
customer1.LastName = "Smith";

Customer customer2 = new Customer();
customer2.FirstName = "Marco";
customer2.ID = 2;
customer2.LastName = "Polo";

this.cmbTest.Items.Add(customer1);
this.cmbTest.Items.Add(customer2);

this.cmbTest.DisplayMember = "FirstName";
this.cmbTest.ValueMember = "ID";

Or you can use a datasource:
Customer customer1 = new Customer();
customer1.FirstName = "John";
customer1.ID = 1;
customer1.LastName = "Smith";

Customer customer2 = new Customer();
customer2.FirstName = "Marco";
customer2.ID = 2;
customer2.LastName = "Polo";

Customer customer3 = new Customer();
customer3.FirstName = "Tom";
customer3.ID = 3;
customer3.LastName = "Hanks";

List customers = new List();
customers.Add(customer1);
customers.Add(customer2);
customers.Add(customer3);

this.cmbTest.DataSource = objects;

this.cmbTest.DisplayMember = "FullName";
this.cmbTest.ValueMember = "ID";

Additionally you can register for different object types a display and value member. This gives you a lot of flexibility when you have to show information of different objects in the same combobox.
To register a new type call the "RegisterType" method and pass it the type of the object, the name of the property which is used as display member and the name of the property which is used as value member.
this.cmbTest.RegisterType(typeof(Customer), "FirstName", "PK");

To unregister a registered type call "UnregisterType" and pass it the type you want to unregister.
this.cmbTest.UnregisterType(typeof(Customer));

To modify the display and/or value member of a registered type call "ChangeValueMember" or "ChangeDisplayMember" respectively and pass it the new name of the property you want to use.
this.cmbTest.ChangeDisplayMember(typeof(Customer), "FullName");
this.cmbTest.ChangeValueMember(typeof(Customer), "LastName");
Of course all this operations can be performed at runtime and the changes are immediately visible in the combo.
To obtain the value of the selected item, simply call "SelectedValue".
Console.WriteLine(this.cmbTest.SelectedValue.ToString());
To get the selected object simply call "SelectedItem" and cast it to the correct type.
Customer selectedCustomer = this.cmbTest.SelectedItem as Customer;
if (selectedCustomer != null)
{
...
}
NOTE: If the combobox has to visualize a type which is not registered it calls the ToString() method of the object and uses that string.

Now I'd like to show you the read only property. The enhanced combobox provides a read only property which disables the drop down button and changes the back color of the combobox to "Control". The read only property is not a real read only because it is not possible to select and then copy the visible text. The most important point is that you can change the fore- and backcolor of the combobox when it is in read only because it is not very easy to read the text of a disabled combo box. The images below show what I mean.

This is a disabled ComboBox:


This is a read only ComboBox:


You can set any color as read only back- and fore color you like:



That's all about my enhanced Combo Box. I hope it helps someone to achieve what he wants. If you have suggestions on how to improve it or you found a bug, feel free to leave a comment.

You can download the DLL from here and simply drag and drop it to your visual studio toolbox.
Or you can get the source code with a sample tool which shows how to use it from here.

Saturday, June 14, 2008

Problems with Google Earth

Lastly I updated Google Earth to the latest version and after I started it I saw the following:


After searching the Internet I found the page of Google where they give some points which should be checked; such as: install the latest display driver, ...
But I already had the latest drivers.
While browsing trough the options of Google Earth I found that the display mode can be changed. After changing it to DirectX it worked correctly.

To change the setting:
1. go to the options


2. And then change the graphics mode to DirectX


Related links:
Google Earth

Thursday, May 15, 2008

Working with XML files

During my work as developer I have quite often to do with XML files. They are very popular and many data exchange is done with XML and also the file format of Office 2007 is based on XML. To provide a compatibility and avoid parsing errors it is a good idea to create an XML Schema file (.xsd) which describes which structure a XML must have. This allows then to validate an XML file and check if there are errors. Since I am not very good in writing XML Schema files (and often I have no time) I use a tool of Microsoft to generate an XML Schema file from an already existing XML file. The tool is included in the .NET frameworks 1.1 to 3.5. You can simply search in your "C:\Program files" folder for "xsd.exe" and you will find it.
The tool is a command line tool but very very easy to use. To get a schema out of an xml file perform the following steps:
  1. Create an XML file with the desired structure (for simplicity on the desktop)
  2. Search and copy the file "xsd.exe" to the desktop
  3. Open a command line window (Windows key + R -> type "cmd") or (Start -> Run... -> type "cmd")
  4. Navigate to your desktop folder
  5. Then type "xsd.exe myfile.xml"
  6. Use the created file "myfile.xsd" as base for your xml file
Even simpler is to use the freeware tool "XMLFox Advance". You can download it from here.
This applications helps you to create xml files and afterwards you can create the XML Schema file from it.
To validate an existing XML file against an existing XML Schema file with XMLFox you have to modify the preferences of the tool. Go to "Tools->Preferences" and check their the point "Perform validation against XSD schema". After this you can open an XML file with the application, go to the "Script" tab and click on validate. You are asked now which xsd file you want to use. After you selected one the validation is performed and possible errors are displayed in the list at the bottom.

Saturday, April 26, 2008

Who is faster??

Friday 24. of April I attended a conference which was organized by the dotnetpro magazine. The theme of the conference was Jump! and it was intended to give developers an overview of the new features of Visual Studio 2008, .Net framework 3.5 and C# 3.0. It was very interesting to see the new technologies and in which direction we are going. Something that impressed me was the new query language LINQ which can be used to query many kinds of data such as lists, xml files or databases. I was curious about the performance of this new technology and therefore I did some performance tests. I wanted to compare the traditional for loop, the nowadays mainly used foreach loop, the FindAll method of the collections class and LINQ. I executed every "method" two times because especially for LINQ this makes a big difference. The task that each "method" had to perform was to find all values which are bigger than 5 in a list of integers which contains all together 1,000,000 elements and add it to a result list. The result list contained about 400,000 elements because I filled it with a random number between 0 and 10.
Since under windows it is almost impossible to get accurate performance results because services and applications in the background interrupt my test application I run it altogether 10 times and then I took the least value for every "method". I was very impressed of the results, but first I will show you the code that I used:
This is the simple for loop that everybody knows how it works.
for (int i = 0; i <> 5)
result.Add(numbers[i]);
}

Here we have the well known foreach loop which is and should be used.
foreach (int num in numbers)
{
if (num > 5)
result.Add(num);
}

This the FindAll method of the collections class. It uses a predicate to decide which elments should be returned and I used an anonymous delegate to state my condition.
result = numbers.FindAll(new Predicate(delegate(int i) { return i > 5; }));

And finally here we have the LINQ query which looks like SQL and allows to make structured queries in the code. The var keyword in front states that the compiler decides of which type the variable "res" is. In this case it will be a collection of integers.
var res = from num in numbers
where num > 5
select num;

To talk about syntax; I prefer the LINQ syntax, because it is compact, structured and SQL like which many developers know quite well. Moreover when you have to make grouping and you do this with a foreach loop then you require much more lines of code as when you do it with LINQ. And as a speaker on the conference said:
More lines of code contain more errors.

Ok here there is the result of my measurements:



As you can see on the chart above, LINQ is by far the fastest "method" to perform such "queries". I was very impressed by the velocity. The difference between the first run and the second run lies in the implementation of LINQ. A speaker on the conference said that behind the scenes they build a binary tree and use it for searching. Therefore when this tree is build once all following queries are very very fast, also if you change the search condition.
Other things that you can see from the chart is that the good old foor loop is compared to the foreach and the FindAll "methods" the fastest. Despite this fact I will use the foreach loop in future because it is more structured and requires less thinking about the underlying array, list,... because the collection class does the work for you. I was disappointed of the performance of the FindAll method of the collection class. It was the slowest in the test. This could be because it uses predicates and anonymous delegates which may use more resources. The syntax of the FindAll is also compact and after some learning you know how to create anonymous delegates. The advantages of the methods of the collection class such as FindAll, Find, ConvertAll,... is that this features are available already under the .Net 2.0 framework and that you need only one line of code to do such "queries". The big disadvantage is as already said above that it is the slowest method to find a list of elements which satisfy a condition. For the other methods (Find, ConvertAll) I will maybe do some tests to see their performance.

If you are interested to run this performance test on your own machine you can download it here.

Tools used:
Microsoft Visual Studio 2008 Express Edition

Wednesday, April 9, 2008

Dynamic number of parameters

Lastly I realized a very interesting feature of C#; the possibility to have a dynamic number of parameters for methods. This feature can easily be used in any method by specifying the "params" keyword and then providing an array of objects which holds the parameters. This technique allows you to create interesting methods and giving you the possibility to make your code shorter and better understandable.
First of all I'd like you to show an add method which accepts dynamic number of parameters.
public static int Add(params int[] numbersToAdd)
{
int sum = 0;
foreach (int number in numbersToAdd)
{
sum += number;
}
return sum;
}

It can be called in the following two ways:
int[] numbers = new int[4];
numbers[0] = 3;
numbers[1] = 8;
numbers[2] = 22;
numbers[3] = 2;
Console.WriteLine(Add(numbers));
/* OUTPUT
* 35
*/

or
Console.WriteLine(Add(3, 8, 22, 2));
/* OUTPUT
* 35
*/

Which version do you like more? I prefer the second one because I don't have to create an array of integers. Sure this method makes not really sense but it is only for demonstration purposes.
Another interesting method could be written which is the "Concat" method. It basically concatenates every object passed as parameter to a string and returns it:
public static string Concat(params object[] objects)
{
StringBuilder sb = new StringBuilder();
foreach (object obj in objects)
{
sb.Append(obj.ToString());
}
return sb.ToString();
}

The usage of this method would be the following:
Console.WriteLine("\n" + Concat("hello world ", 4, " ", true));
/* OUTPUT
* hello world 4 True
*/

Two other methods which could be interesting are the "Copy" and "CreateAndCopy" methods. The "CreateAndCopy" method takes an object as parameter, creates a new instance of the same type and copies the properties which are specified by their name in the parameters. In addition it is a generic so that no cast is necessary and it can be used with any object. Note that when calling this method the type has not necessarily be specified because C# defers the type from the object passed.
public static T CreateAndCopy<T>(T source, params string[] propertiesToCopy)
{
T target = (T)System.Activator.CreateInstance(typeof(T));
foreach (string propertyName in propertiesToCopy)
{
PropertyInfo property = typeof(T).GetProperty(propertyName);
property.SetValue(target, property.GetValue(source, null), null);
}
return target;
}

It can be used like this:
MyObject o1 = new MyObject();
o1.Text = "hallo";
o1.Number = 99;
o1.Boolean = true;

Console.WriteLine(o1.ToString());
/* OUTPUT
* MyObject:
* Text -> hallo
* Number -> 99
* Boolean -> True
*/

MyObject newObj = CreateAndCopy(o1, "Text", "Boolean");
Console.WriteLine(newObj.ToString());
/* OUTPUT
* MyObject:
* Text -> hallo
* Number -> 0
* Boolean -> True
*/

The "Copy" method does something similar but it accepts a destination object to which the values of the specified properties are copied to:
public static T Copy<T>(T source, T destination, params string[] propertiesToCopy)
{
foreach (string propertyName in propertiesToCopy)
{
PropertyInfo property = typeof(T).GetProperty(propertyName);
property.SetValue(destination, property.GetValue(source, null), null);
}
return destination;
}

CONCLUSION:
The possibility to specify variable number of parameters may sometimes help to make the code easier to read and better understandable but in some circumstances it is better to create a class which holds all the required values and pass an instance of it to a method.

Monday, April 7, 2008

Generic progress dialog

Quite often I have to perform long operations in an application and then I want to show a progress bar to the user that he can see that the application is working and how long it will take. My requirements for the progress bar dialog are:
  • it should be generic and therefore not be tied with the work which has to be done
  • it should not block or freeze the main application
  • the user must have the possibility to abort the operation
It turned out that it is quite challenging to meet all these requirements. With different approaches I had different problems and could not fulfill my requirements. For example there was a version where the progress dialog was not updated or the user could not abort the operation. After some trying I found a quite usable solution. The main application uses a backgroundworker to do the work; this has the advantage that the computation is done in a different thread and the backgroundwoker provides cancel and progress notification. My progress bar dialog is started also in its own thread to make sure that its graphics are not blocked and updated when needed. With this "architecture" it is even possible that the main application performs some other operations while a heavy work is done and the progress shown to the user. The progress dialog provides all its functionalities through static methods which access a "private singleton". This means that the developer never gets an instance of the progress dialog and that at most one instance of the progress dialog exists. To notify the main application about the cancel event I used an event with a delegate. Therefore the main application can do what it wants when the user presses cancel.
When the user presses cancel then a message box is shown which asks if he really wants to abort. The nice thing with this implementation is that while this message box is shown the computation goes on and is not blocked.

The following code shows the progress bar, sets the title and message, assigns a method to the cancel event and starts the computation if the background worker is not already working:
if (!this.backgroundWorker.IsBusy)
{
this.Enabled = false; /*lock the main application*/
ProgressDialog.Show(max);
ProgressDialog.SetTitle("this is the title");
ProgressDialog.SetMessage("I am the message for the very long task. Please be patient and wait...");
ProgressDialog.CancelEvent += new ProgressDialog.CancelEventHandler(pd_CancelEvent);
this.backgroundWorker.RunWorkerAsync();
}

Important is to set the cancellation property of the background worker to true; this is best done in the designer or in the constructor of the main form:
this.backgroundWorker.WorkerSupportsCancellation = true;

The computation is done in the do_work event of the background worker. Here is important that in the loop the check for the cancel event is done because otherwise the backgroundworker will not stop on cancel. To update the progress bar it is enough to call the SetValue method of the progress dialog. This is only a very stupid operation for demonstration:
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < max; i++)
{
/*this check is needed in order to abort the operation if the user has clicked on cancel*/
if (this.backgroundWorker.CancellationPending)
{
e.Cancel = true;
return;
}

ProgressDialog.SetValue(i); /*update the value*/
Console.WriteLine(i);
}
}

Another thing that I have to mention. In debug mode there occurs always an exception which says that this operations are not thread safe. Till now I did not had the time to look how I can make this code thread safe, but as soon as I have a thread safe version (if one exists) I will post it.
UPDATE:
I finally had the time to learn how to write thread safe method calls. The code below shows how it is done. First you have to check if the mehtod was called by a Thread other than the own Thread. This does the property "InvokeRequired". If so a delegate is created and the method is called with "Invoke".
public static void SetTitle(string title)
{
if (instance.InvokeRequired) /*if another thread called this method*/
{
SetTitleCallback s = new SetTitleCallback(SetTitle);
instance.Invoke(s, title);
}
else
{
instance.Text = title;
}
}

You can download the full demo project here.

Finally a screenshot on how my progress bar dialog looks like:


If you have suggestions, ideas or You know how to improve this code or if You have a thread save version You are welcome to post a comment.