A couple of weeks ago i decided to install Vista Ultimate… Despite the marketing efforts my only Wow experience was yesterday when i decided to remove it… (Simply boot with your XP installation cd, run fixboot and fixmbr from the rescue console and you’re set
)
Monthly Archives: January 2007
About the Wow, i removed Vista from my harddisk, experience
Presenting the DataGridViewLargeTextBoxCell
Today i decided to experiment a bit with custom DataGridViewCell implementations. If you insert large text into a DataGridView it will (at best) wrap the text. I wanted my DataGridView to behave like Excel so that the whole text is displayed. Here are a couple of screenshots of the result:


Feel free to download CustomDataGridViewCells.zip.
About Thread-Safe GUI…
If you’re writing windows applications you’ll most certainly recognize the following piece of code:
private delegate void UpdateIntResultDelegate(int result);
private void UpdateIntResult(int result)
{
if (this.labelIntResult.InvokeRequired)
this.labelIntResult.Invoke(new UpdateIntResultDelegate(this.UpdateIntResult), result);
else
this.myDataSource.IntResult = result;
}
private delegate void UpdateStringResultDelegate(string result);
private void UpdateStringResult(string result)
{
if (this.labelStringResult.InvokeRequired)
this.labelStringResult.Invoke(new UpdateStringResultDelegate(this.UpdateStringResult), result);
else
this.myDataSource.StringResult = result;
}
Today i was fed up with defining all these Delegates.. So i decided to define a generic delegate instead:
delegate void Delegate<t>(T t);
And now i can reuse this Delegate for my two update methods:
private void UpdateIntResult(int result)
{
if (this.labelIntResult.InvokeRequired)
this.labelIntResult.Invoke(new Delegate<int>(this.UpdateIntResult), result);
else
this.myDataSource.IntResult = result;
}
private void UpdateStringResult(string result)
{
if (this.labelStringResult.InvokeRequired)
this.labelStringResult.Invoke(new Delegate<string>(this.UpdateStringResult), result);
else
this.myDataSource.StringResult = result;
}
Apparently (and not surprisingly) i’m not the first to come up with this idea, a little websearch for ‘Generic Delegate’ learned me that Roy Osherove blogged about it in: The 3 ways to create a Thread-Safe GUI with .NET 2.0, with one clear winner. After reading the article i decided to take the following approach (The call to UpdateIntResult is type-safe, it only calls Invoke when it’s required and no duplication):
void UpdateIntResult(int result)
{
if (this.labelIntResult.InvokeRequired)
{
this.labelIntResult.Invoke(new MethodInvoker(delegate { this.UpdateIntResult(result); }));
}
else
{
this.myDataSource.IntResult = result;
}
}
Reading and writing unmanged structs from binary files
I still remember one of the first tasks during my internship (At a software shop that still used Visual Studio 6 as development environment) last year: Develop a GUI application using .Net that allows the user to manipulate data stored in a binary file which was generated by c/c++ program. As a newcomer to C# programming i just couldn’t find the right attributes to Marshal the following structs:
struct test1 {
char name[9];
int score;
};
struct test2 {
test1 items[10];
}
After a couple of days they wanted me to deliver a product, so i decided to stop experimenting and wrote the application in C++ (Example). Since i don’t like unanswered questions, i decided to give it another try this afternoon… It didn’t take long to come up with the following:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=4)]
struct Test1
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=9)]
public string Name;
public int Score;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=4)]
struct Test2
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst=10)]
public Test1[] Items;
}
static object Read(Stream stream, Type t)
{
byte[] buffer = new byte[Marshal.SizeOf(t)];
for (int read = 0; read < buffer.Length; read += stream.Read(buffer, read, buffer.Length)) ;
GCHandle gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
object o = Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), t);
gcHandle.Free();
return o;
}
static void Write(Stream stream, object o)
{
byte[] buffer = new byte[Marshal.SizeOf(o.GetType())];
GCHandle gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
Marshal.StructureToPtr(o, gcHandle.AddrOfPinnedObject(), true);
stream.Write(buffer, 0, buffer.Length);
gcHandle.Free();
}
static void Main(string[] args)
{
Test1 test1 = new Test1();
test1.Name = "timvw";
test1.Score = 100;
using (FileStream fileStream = new FileStream(@"c:\test.dat", FileMode.OpenOrCreate))
{
Write(fileStream, test1);
fileStream.Seek(0, SeekOrigin.Begin);
Test1 test2 = (Test1) Read(fileStream, typeof(Test1));
Console.WriteLine("Name: {0} Score: {1}", test2.Name, test2.Score);
}
Console.Write("{0}Press any key to continue...", Environment.NewLine);
Console.ReadKey();
}
Exploring DataGridViewComboBoxColumn databinding
Let’s start with a simple example: Each Person has a Name (string) and PersonTypeCode (an Enumerated value) property. We drag a DataGridView on the designer form and add two columns (DataGridViewComboBoxColumn for the PersonTypeCode property). And then we hook up the Bindingsource as following:
class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.dataGridView1.AutoGenerateColumns = false;
this.ColumnName.DataPropertyName = "Name";
this.ColumnPersonTypeCode.DataPropertyName = "PersonTypeCode";
BindingSource bindingSource = new BindingSource();
bindingSource.DataSource = FindPersons();
this.dataGridView1.DataSource = bindingSource;
}
private BindingList<person> FindPersons()
{
BindingList<person> bindingList = new BindingList<person>();
bindingList.Add(new Person("Timvw", PersonTypeCode.Geek));
bindingList.Add(new Person("John Doe", PersonTypeCode.Anonymous));
bindingList.Add(new Person("An Onymous", PersonTypeCode.Anonymous));
bindingList.Add(new Person("Jenna Jameson", PersonTypeCode.Babe));
return bindingList;
}
}
enum PersonTypeCode
{
Geek = 0,
Anonymous = 1,
Babe = 2
}
class Person
{
private PersonTypeCode personTypeCode;
private string name;
public Person(string name, PersonTypeCode personTypeCode)
{
this.name = name;
this.personTypeCode = personTypeCode;
}
public string Name
{
get { return this.name; }
set { this.name = value; }
}
public PersonTypeCode PersonTypeCode
{
get { return this.personTypeCode; }
set { this.personTypeCode = value; }
}
}
If we run this code we run in the following error:

Always make sure the DataGridViewComboxColumn knows about all the possible values (Add them via the Items property or use databinding). Let’s extend our Form1 class as following:
public Form1()
{
InitializeComponent();
this.dataGridView1.AutoGenerateColumns = false;
this.ColumnName.DataPropertyName = "Name";
this.ColumnPersonTypeCode.DataPropertyName = "PersonTypeCode";
this.ColumnPersonTypeCode.DataSource = FindPersonTypeCodes();
BindingSource bindingSource = new BindingSource();
bindingSource.DataSource = FindPersons();
this.dataGridView1.DataSource = bindingSource;
}
private BindingList<personTypeCode> FindPersonTypeCodes()
{
BindingList<personTypeCode> bindingList = new BindingList<personTypeCode>();
foreach (PersonTypeCode personTypeCode in Enum.GetValues(typeof(PersonTypeCode)))
{
bindingList.Add(personTypeCode);
}
return bindingList;
}
Allright, here is a screenshot of our first working version:

Instead of displaying the bare enum values we want to display a nice label. In order to achieve this we define a class PersonType to hold both the PersonTypeCode and the label:
class PersonType
{
private PersonTypeCode personTypeCode;
private string label;
public PersonType(string label, PersonTypeCode personTypeCode)
{
this.label = label;
this.personTypeCode = personTypeCode;
}
public string Label
{
get { return this.label; }
set { this.label = value; }
}
public PersonTypeCode PersonTypeCode
{
get { return this.personTypeCode; }
set { this.personTypeCode = value; }
}
}
We modify our code so that this new PersonType class is used for the ComboBoxColumn:
public Form1()
{
InitializeComponent();
this.dataGridView1.AutoGenerateColumns = false;
this.ColumnName.DataPropertyName = "Name";
this.ColumnPersonTypeCode.DataPropertyName = "PersonTypeCode";
this.ColumnPersonTypeCode.DisplayMember = "Label";
this.ColumnPersonTypeCode.ValueMember = "PersonTypeCode";
this.ColumnPersonTypeCode.DataSource = FindPersonTypes();
BindingSource bindingSource = new BindingSource();
bindingSource.DataSource = FindPersons();
this.dataGridView1.DataSource = bindingSource;
}
private BindingList<personType> FindPersonTypes()
{
BindingList<personType> bindingList = new BindingList<personType>();
bindingList.Add(new PersonType("A geeky person", PersonTypeCode.Geek));
bindingList.Add(new PersonType("A coward", PersonTypeCode.Anonymous));
bindingList.Add(new PersonType("Feeling hot hot hot", PersonTypeCode.Babe));
return bindingList;
}

Great! Now we’ll add some functionality that limits the possible values in the ComboBoxColumn basesd on the Name (I already demonstrated this technique here). Simply handle the EditingControlShowing Event on the DataGridView as following:
void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
BindingSource bindingSource = this.dataGridView1.DataSource as BindingSource;
Person person = bindingSource.Current as Person;
BindingList<personType> bindingList = this.FindPersonTypes(person);
DataGridViewComboBoxEditingControl comboBox = e.Control as DataGridViewComboBoxEditingControl;
comboBox.DataSource = bindingList;
}
private BindingList<personType> FindPersonTypes(Person person)
{
// by default, all persons simply have one of the available persontypecodes
BindingList<personType> bindingList = FindPersonTypes();
if (person.PersonTypeCode == PersonTypeCode.Geek)
{
// geeks are doomed to stay geeks
bindingList.RemoveAt(2);
bindingList.RemoveAt(1);
}
return bindingList;
}
If you open the combox for “Timvw” you see that you can only choose “A geeky person”:

Instead of using an enum we could have used a regular class too. The key is to override the Equals method:
class PersonTypeCode
{
public static PersonTypeCode Geek
{
get { return new PersonTypeCode(0); }
}
public static PersonTypeCode Anonymous
{
get { return new PersonTypeCode(1); }
}
public static PersonTypeCode Babe
{
get { return new PersonTypeCode(2); }
}
private int id;
public PersonTypeCode(int id)
{
this.id = id;
}
public override bool Equals(object obj)
{
if (obj == null) return false;
if (obj == this) return true;
PersonTypeCode personTypeCode = obj as PersonTypeCode;
if (personTypeCode == null) return false;
return this.id == personTypeCode.id;
}
public override int GetHashCode()
{
return this.id.GetHashCode();
}
}
private BindingList<personType> FindPersonTypes(Person person)
{
// by default, all persons simply have one of the available persontypecodes
BindingList<personType> bindingList = FindPersonTypes();
//if (person.PersonTypeCode == PersonTypeCode.Geek)
if (person.PersonTypeCode.Equals(PersonTypeCode.Geek))
{
// geeks are doomed to stay geeks
bindingList.RemoveAt(2);
bindingList.RemoveAt(1);
}
return bindingList;
}
And now you’re thinking: But i want the user to not select a PersonTypeCode (null). We’ll represent that with an empty string “”:
private BindingList<person> FindPersons()
{
BindingList<person> bindingList = new BindingList<person>();
bindingList.Add(new Person("Timvw", PersonTypeCode.Geek));
bindingList.Add(new Person("John Doe", PersonTypeCode.Anonymous));
bindingList.Add(new Person("An Onymous", PersonTypeCode.Anonymous));
bindingList.Add(new Person("Jenna Jameson", PersonTypeCode.Babe));
bindingList.Add(new Person("Null Able", null));
return bindingList;
}
private BindingList<personType> FindPersonTypes()
{
BindingList<personType> bindingList = new BindingList<personType>();
bindingList.Add(new PersonType("A geeky person", PersonTypeCode.Geek));
bindingList.Add(new PersonType("A coward", PersonTypeCode.Anonymous));
bindingList.Add(new PersonType("Feeling hot hot hot", PersonTypeCode.Babe));
bindingList.Add(new PersonType(string.Empty, null));
return bindingList;
}
private BindingList<personType> FindPersonTypes(Person person)
{
// by default, all persons simply have one of the available persontypecodes
BindingList<personType> bindingList = FindPersonTypes();
if (person.PersonTypeCode != null && person.PersonTypeCode.Equals(PersonTypeCode.Geek))
{
// geeks are doomed to stay geeks
bindingList.RemoveAt(2);
bindingList.RemoveAt(1);
}
return bindingList;
}

When the user starts editing the record, the combobox will choose the first item in the list (A geeky person). Now we change this behaviour so that the actual PersonTypeCode is selected:
void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (this.dataGridView1.CurrentCell.ColumnIndex == this.ColumnPersonTypeCode.Index)
{
BindingSource bindingSource = this.dataGridView1.DataSource as BindingSource;
Person person = bindingSource.Current as Person;
BindingList<personType> bindingList = this.FindPersonTypes(person);
DataGridViewComboBoxEditingControl comboBox = e.Control as DataGridViewComboBoxEditingControl;
comboBox.DataSource = bindingList;
if (person.PersonTypeCode != null)
{
comboBox.SelectedValue = person.PersonTypeCode;
}
else
{
comboBox.SelectedValue = string.Empty;
}
}
}

In order to make the DataGridView more usable we set the EditMode property to EditOnEnter. Selected values in the ComboBox are only commited when the user leaves the current cell. Handling the SelectionChangeCommited event on the ComboBox allows us to commit that value without requiring the user to leave the current cell:
void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (this.dataGridView1.CurrentCell.ColumnIndex == this.ColumnPersonTypeCode.Index)
{
BindingSource bindingSource = this.dataGridView1.DataSource as BindingSource;
Person person = bindingSource.Current as Person;
BindingList<personType> bindingList = this.FindPersonTypes(person);
DataGridViewComboBoxEditingControl comboBox = e.Control as DataGridViewComboBoxEditingControl;
comboBox.DataSource = bindingList;
if (person.PersonTypeCode != null)
{
comboBox.SelectedValue = person.PersonTypeCode;
}
else
{
comboBox.SelectedValue = string.Empty;
}
comboBox.SelectionChangeCommitted -= this.comboBox_SelectionChangeCommitted;
comboBox.SelectionChangeCommitted += this.comboBox_SelectionChangeCommitted;
}
}
void comboBox_SelectionChangeCommitted(object sender, EventArgs e)
{
this.dataGridView1.EndEdit();
}
Now it’s up to you to apply these simple techniques and build great software. Feel free to download the complete source: DataGridViewComboBoxBinding.zip.
Making WebRequests in parallel…
Under the assumption that making sequential WebRequests is slower than making them in parallel i wrote a little program that returns the HTTP status code for each URI in a list. Because the number of WaitHandles on a system is limited to 64 and i would have been required to hack around this limitation i decided to use ThreadPool instead…
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Net;
namespace ManyRequests
{
class Program
{
static void Main(string[] args)
{
List<uri> uris = new List<uri>();
uris.Add(new Uri("http://www.timvw.be"));
uris.Add(new Uri("http://example.com/does_not_exist"));
uris.Add(new Uri("http://www.timvw.be/c-sharp"));
uris.Add(new Uri("http://www.timvw.be/rss-feed/"));
uris.Add(new Uri("http://localhost"));
Console.WriteLine("Getting the HttpStatusCodes...");
HttpStatusCodeReader httpStatusCodeReader = new HttpStatusCodeReader(uris);
int[] httpStatusCodes = httpStatusCodeReader.GetHttpStatusCodes();
for (int i = 0; i < uris.Count; ++i)
{
Console.WriteLine("{0} {1}", httpStatusCodes[i], uris[i]);
}
Console.Write("{0}Press any key to continue…", Environment.NewLine);
Console.ReadKey();
}
}
public class HttpStatusCodeReader
{
private List<uri> uris;
private int[] httpStatusCodes;
private object syncLock;
private int completed;
public HttpStatusCodeReader(List<uri> uris)
{
if (uris == null)
{
throw new ArgumentNullException("uris");
}
foreach (Uri uri in uris)
{
if (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps)
{
throw new ArgumentException(uri.ToString() + " is not valid http(s) uri.", "uris");
}
}
this.uris = uris;
this.httpStatusCodes = new int[uris.Count];
this.syncLock = new object();
this.completed = 0;
}
public int[] GetHttpStatusCodes()
{
for (int i = 0; i < this.httpStatusCodes.Length; ++i)
{
HttpWebRequest httpWebRequest = WebRequest.Create(this.uris[i]) as HttpWebRequest;
httpWebRequest.Method = "HEAD";
httpWebRequest.AllowAutoRedirect = true;
httpWebRequest.BeginGetResponse(this.GetResponseCompleted, new object[] { httpWebRequest, i });
}
lock (this.syncLock)
{
while (this.completed < this.httpStatusCodes.Length)
{
Monitor.Wait(this.syncLock);
}
}
return this.httpStatusCodes;
}
private void GetResponseCompleted(IAsyncResult ar)
{
object[] objects = ar.AsyncState as object[];
HttpWebRequest httpWebRequest = objects[0] as HttpWebRequest;
int index = (int)objects[1];
HttpWebResponse httpWebResponse = null;
try
{
httpWebResponse = httpWebRequest.EndGetResponse(ar) as HttpWebResponse;
this.httpStatusCodes[index] = (int)httpWebResponse.StatusCode;
}
catch (WebException webException)
{
httpWebResponse = webException.Response as HttpWebResponse;
if (httpWebResponse != null)
{
this.httpStatusCodes[index] = (int)httpWebResponse.StatusCode;
}
}
finally
{
if (httpWebResponse != null)
{
httpWebResponse.Close();
}
lock (this.syncLock)
{
Interlocked.Add(ref this.completed, 1);
Monitor.Pulse(this.syncLock);
}
}
}
}
}
Hide and unhide columns (or rows) in the DataGridView
Once in a while i see the following question:
I have to create a customized datagridview to enable the expandable columns. Expandable column in the sense drilling down the columns…. One column can hide multiple columns. The user can see the child columns by clicking the + button before the column name
Using the Visibile property of the DataGridViewColumn makes this a no-brainer. Let’s take the Databound DataGridView and implement functionality to hide/unhide the quarterly results. All you have to do is add a DataGridViewButtonColumn and handle the DataGridView CellClick event as following:
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == this.ColumnButton.Index)
{
bool visible = !this.ColumnQ1.Visible;
this.ColumnQ1.Visible = visible;
this.ColumnQ2.Visible = visible;
this.ColumnQ3.Visible = visible;
this.ColumnQ4.Visible = visible;
this.ColumnButton.HeaderText = visible ? "-" : "+";
}
}
This is how it looks like:


Feel free to download the updated source code for DataGridViewDataSource.zip.
Presenting a Generic RemotingHelper
Last couple of months i’ve been experimenting with Remoting. Here is a class that helps a client to acquire proxies to an endpoint served by the requested well-known object:
public static class RemotingHelper
{
static RemotingHelper()
{
RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, false);
}
private static object GetService(string fullName)
{
WellKnownClientTypeEntry[] wellKnownClientTypeEntries = RemotingConfiguration.GetRegisteredWellKnownClientTypes();
foreach (WellKnownClientTypeEntry welknownClientTypeEntry in wellKnownClientTypeEntries)
{
if (welknownClientTypeEntry.ObjectType.FullName == fullName)
{
return Activator.GetObject(welknownClientTypeEntry.ObjectType, welknownClientTypeEntry.ObjectUrl);
}
}
throw new ArgumentException(fullName + " is not a wellKnownClientType.");
}
public static T GetService<t>()
{
return (T) RemotingHelper.GetService(typeof(T).FullName);
}
}
Getting a proxy is as easy as (Presuming that you’ve configured the system.runtime.remoting in your App.config):
IContract contract = RemotingHelper.GetService<icontract>();
Databinding a Nullable <T> property
I find it frustrating that data binding does not really support Nullable<T>. Anyway, it’s relatively easy to workaround this shortcoming:
public partial class Form1 : Form
{
private MyDataSource myDataSource;
public Form1()
{
InitializeComponent();
this.myDataSource = new MyDataSource();
this.textBox1.DataBindings.Add("Text", this.myDataSource, "Double", true);
this.textBox1.DataBindings["Text"].Parse += this.Text_Parse;
}
void Text_Parse( object sender, ConvertEventArgs e )
{
if( e.Value == null || e.Value.ToString().Length == 0 )
{
e.Value = null;
}
}
private void buttonTellMe_Click(object sender, EventArgs e)
{
if (this.myDataSource.Double.HasValue)
{
MessageBox.Show("The double is: " + this.myDataSource.Double);
}
else
{
MessageBox.Show("The double is null");
}
}
}
class MyDataSource
{
private double? _double;
public double? Double
{
get { return this._double; }
set { this._double = value; }
}
}


Generating UTF-8 with System.Xml.XmlWriter
Today i decided to experiment with XmlWriter. The first i wanted to do was set the Encoding to UTF-8.:
StringBuilder stringBuilder = new StringBuilder(); XmlWriter xmlWriter = XmlWriter.Create(stringBuilder); xmlWriter.Settings.Encoding = Encoding.UTF8;
When i ran this code i recieved the following exception: XmlException was unhandled: The ‘XmlWriterSettings.Encoding’ property is read only and cannot be set. The documentation for the Settings property clearly says:
The XmlWriterSettings object returned by the Settings property cannot be modified. Any attempt to change individual settings results in an exception being thrown.
So i wrote the following:
StringBuilder stringBuilder = new StringBuilder();
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Encoding = Encoding.UTF8;
XmlWriter xmlWriter = XmlWriter.Create(stringBuilder, xmlWriterSettings);
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("root", "http://www.timvw.be/ns");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
xmlWriter.Flush();
xmlWriter.Close();
string xmlString = stringBuilder.ToString();
As you can see: <?xml version=”1.0″ encoding=”utf-16″?><root xmlns=”http://www.timvw.be/ns” /> is still not what i want. Apparently is the Encoding property ignored if the XmlWriter is not using a Stream. So here is my next attempt:
MemoryStream memoryStream = new MemoryStream(); // initialize xmlWriterSettings as above... XmlWriter xmlWriter = XmlWriter.Create(memoryStream, xmlWriterSettings); // call the same operations on the xmlWriter as above... string xmlString = Encoding.UTF8.GetString(memoryStream.ToArray());
Ok, i’m getting close: ?<?xml version=”1.0″ encoding=”utf-8″?><root xmlns=”http://www.timvw.be/ns” />. Luckily enough i knew that the ? (byte with value 239) at the beginning is the BOM. In order to get rid of that byte i had to create my own instance of UTF8Encoding. Finally, i can present some working code:
MemoryStream memoryStream = new MemoryStream();
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Encoding = new UTF8Encoding(false);
xmlWriterSettings.ConformanceLevel = ConformanceLevel.Document;
xmlWriterSettings.Indent = true;
XmlWriter xmlWriter = XmlWriter.Create(memoryStream, xmlWriterSettings);
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("root", "http://www.timvw.be/ns");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
xmlWriter.Flush();
xmlWriter.Close();
string xmlString = Encoding.UTF8.GetString(memoryStream.ToArray());