How can I put a checkbox in a column of my DataGrid

You create a custom DataTableStyle that contains column styles for each column you want to display. You add the column styles in the order you want them to appear. Here are the steps to add an string column, an int column and a bool check column to a DataGrid. You can also download a working project. // code assumes you have a DataSet named myDataSet, a table named ”EastCoastSales” and a DataGrid myDataGrid //STEP 1: Create a DataTable style object and set properties if required. DataGridTableStyle ts1 = new DataGridTableStyle(); //specify the table from dataset (required step) ts1.MappingName = ”EastCoastSales”; // Set other properties (optional step) ts1.AlternatingBackColor = Color.LightBlue; //STEP 2: Create a string column and add it to the tablestyle DataGridColumnStyle TextCol = new DataGridTextBoxColumn(); TextCol.MappingName = ”custName”; //from dataset table TextCol.HeaderText = ”Customer Name”; TextCol.Width = 250; ts1.GridColumnStyles.Add(TextCol); //STEP 3: Create an int column style and add it to the tablestyle //this requires setting the format for the column through its property descriptor PropertyDescriptorCollection pdc = this.BindingContext [myDataSet, ”EastCoastSales”].GetItemProperties(); //now created a formated column using the pdc DataGridDigitsTextBoxColumn csIDInt = new DataGridDigitsTextBoxColumn(pdc[”CustID”], ”i”, true); csIDInt.MappingName = ”CustID”; csIDInt.HeaderText = ”CustID”; csIDInt.Width = 100; ts1.GridColumnStyles.Add(csIDInt); //STEP 4: Add the checkbox DataGridColumnStyle boolCol = new DataGridBoolColumn(); boolCol.MappingName = ”Current”; boolCol.HeaderText = ”Info Current”; //uncomment this line to get a two-state checkbox //((DataGridBoolColumn)boolCol).AllowNull = false; boolCol.Width = 150; ts1.GridColumnStyles.Add(boolCol); //STEP 5: Add the tablestyle to your datagrid’s tablestlye collection myDataGrid.TableStyles.Add(ts1);

MeasureString seems to have problems with white space and punctuation. Is there a better method to use

Try calling one of the overloads of MeasureString that takes an StringFormat parameter and pass it StringFormat.GenericTypographic. Here is some code that shows the same string and font giving different results depending upon the StringFormat parameter. StringFormat sf = new StringFormat(StringFormat.GenericTypographic); SizeF size = e.Graphics.MeasureString(‘this has some words’, Font, 500, sf); SizeF size1 = e.Graphics.MeasureString(‘this has some words’, Font); string s = string.Format(‘GenericTypographic={0:f2} GenericDefault={1:f2}’, size.Width, size1.Width); MessageBox.Show(s);

How can I persist a collection of items into code

The CollectionEditor allows adding and removing items from a collection at design time. If the items in this collection implement IComponent or if they are derived from Component, the items in your collection can be persisted in code. Download collectioneditorsample.zip for a complete sample project. Here are some steps you should follow: 1) Make sure your item is derived from Component or implements Icomponent. For example: public class SomeItem : Component { private string label = ””; public SomeItem() { } public SomeItem(string label) { this.label = label; } public string Label { get { return label; } set { label = value; } } public override string ToString() { return String.Format(”SomeItem: ( Label = ’{0}’ )”, label); } } 2) Next implement your Collection. You have to implement the Ilist interface. The CollectionEditor will determine the type of instances to be added to your collection using reflection inspecting the return type of the Item property (Indexer). [ Description(”The set of properties to be edited with CollectionEditor.”), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), Editor(typeof(System.ComponentModel.Design.CollectionEditor), typeof(System.Drawing.Design.UITypeEditor)) ] public SomeItemCollection SomeItems { get { if (someItemCollection == null) { someItemCollection = CreateItemCollection(); } return someItemCollection; } } protected SomeItemCollection CreateItemCollection() { return new SomeItemCollection(this); } public class SomeItemCollection : IList { // Fields private SomeItemDisplayer owner; public event EventHandler Changed; // Constructors public SomeItemCollection(SomeItemDisplayer owner) { this.owner = owner; } internal ArrayList InnerArray { get { return owner.someItems; } } public void OnChanged() { if (this.Changed != null) this.Changed(this, EventArgs.Empty); } /// /// The CollectionEditor will determine the type of objects to be created by /// looking at the property type of the following method. CollectionEditor /// internally uses reflection to get the PropertyInfo for the ”Item” property. /// This method must be public. /// public SomeItem this[int index] { set { if (value == null) throw new ArgumentNullException(”value”); if (index < 0 || index >= this.InnerArray.Count) throw new ArgumentOutOfRangeException(String.Format(”Invalid Argument {0}: {1}”, ”index”, index.ToString())); this.InnerArray[index] = value; OnChanged(); } get { if (index < 0 || index >= this.InnerArray.Count) throw new ArgumentOutOfRangeException(”Invalid Argument {0}: {1}”, ”index”, index.ToString()); return (SomeItem) this.InnerArray[index]; } } public void AddRange(object[] items) { InnerArray.AddRange(items); OnChanged(); } /// /// This implementation for the Item property for the IList interface. It’s /// property type is object. /// object IList.this[int index] { set { // forward call to public indexer this[index] = (SomeItem) value; } get { // forward call to public indexer return this[index]; } } public /*IEnumerable*/ IEnumerator GetEnumerator() { return InnerArray.GetEnumerator(); } public /*ICollection*/ int Count { get { return InnerArray.Count; } } public /*IList*/ void RemoveAt(int index) { if (index < 0 || index >= this.InnerArray.Count) throw new ArgumentOutOfRangeException(String.Format(”Invalid Argument {0}: {1}”, ”index”, index.ToString())); this.InnerArray.RemoveAt(index); OnChanged(); } public /*IList*/ void Remove(object value) { int n = this.InnerArray.IndexOf(value,0); if (n != -1) this.RemoveAt(n); } public /*IList*/ void Insert(int index, object item) { if (item == null) throw new ArgumentNullException(”item”); if (index < 0 || index > this.InnerArray.Count) throw new ArgumentOutOfRangeException(String.Format(”Invalid Argument {0}: {1}”,”index”, index.ToString())); this.InnerArray.Insert(index,item); OnChanged(); } public /*IList*/ int IndexOf(object value) { if (value == null) throw new ArgumentNullException(String.Format(”Invalid Argument {0}: {1}”,”value”, ”null”)); return this.InnerArray.IndexOf(value,0); } public /*IList*/ bool IsReadOnly { get { return false; } } public /*IList*/ void Clear() { InnerArray.Clear(); this.owner.Invalidate(); } public /*IList*/ bool Contains(object value) { return this.IndexOf(value) != -1; } void System.Collections.ICollection.CopyTo(Array dest, int index) { int count = this.InnerArray.Count; for (int n1 = 0; n1 < count; n1++) dest.SetValue(this.InnerArray[n1], (n1 + index)); } int System.Collections.IList.Add(object item) { int n = this.InnerArray.Add(item); OnChanged(); return n; } bool System.Collections.IList.IsFixedSize { get { return false; } } bool System.Collections.ICollection.IsSynchronized { get { return false; } } object System.Collections.ICollection.SyncRoot { get { return this; } } } 3) Reference this collection in your control or component that should be designable. You need to supply a DesignerSerializationVisibility and an Editor attribute: private SomeItemCollection someItemCollection = null; ArrayList someItems = new ArrayList(); [ Description(”The set of properties to be edited with CollectionEditor.”), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), Editor(typeof(System.ComponentModel.Design.CollectionEditor), typeof(System.Drawing.Design.UITypeEditor)) ] public SomeItemCollection SomeItems { get { if (someItemCollection == null) { someItemCollection = CreateItemCollection(); } return someItemCollection; } } protected SomeItemCollection CreateItemCollection() { return new SomeItemCollection(this); }

How can I make my controls transparent so the form’s background image can show through them

By default, a control’s background color will be the same as the container’s background. In the picture below, the form’s background was set to Color.Red. In design mode, you can see the four controls have the red background, but since the form’s Image was set to a bitmap, you cannot see the form’s red background. To make the controls’ background transparent, you can set the alpha blend value of their background to zero. In code, you could use: public Form1() { InitializeComponent(); checkBox1.BackColor = Color.FromArgb(0, checkBox1.BackColor); button1.BackColor = Color.FromArgb(0, button1.BackColor); linkLabel1.BackColor = Color.FromArgb(0, linkLabel1.BackColor); label1.BackColor = Color.FromArgb(0, label1.BackColor); // Or use the System.Drawing.Color.Transparent color. } In design mode, you can set the alpha blend value to zero by typing the four component in the property grid. So, for each control’s BackColor property, you would type 0,255,0,0 to make it a transparent red. Here is a VB project using this idea.

I want to do custom handling of special keys such as the Tab key or F2 in the TextBox of a column in the DataGrid. How do I subclass this TextBox to get at it virtual members

The TextBox property of the DataGridTextBoxColumn is ReadOnly, so you just cannot set a new derived TextBox into it. One solution is to derive a TextBox, and then have it use the derived TextBox in the DataGridTextBoxColumn instead of the ‘generic’ TextBox that is there. This is the same technique used in our combobox in a column sample. In that sample, the generic textbox was ‘replaced’ with a combobox. Here, we replace it with a derived TextBox where we can easily override virtual members.   A reasonable question is why not just use the event mechanism of the existing TextBox to modify behavior. Events like KeyPress would allow us to do some things PROVIDED they get hit. Due to the key processing architecture of the FrameWork, for some special keys, these key events are not always fired. And if they are fired, sometimes it is impossible to avoid the default processing if this is the intent you have. Overriding a virtual function, doing something special, and then NOT calling the baseclass is a standard way of avoiding default processing.   In this sample (both VB and CS), we override PreProcessMessage and avoid processing the Keys.Tab key. You can modify the code to not process Keys.F2 as well. DataGridTextBoxColumn is subclassed so it can use our derived TextBox.