How can I do cell by cell validation in a datagrid

There are problems trying to implement cell by cell validation using the grid’s Validating event architecture. The problem is that the grid is not the object handling the data. Instead, a TextBox or some other control is the control managing the changing of the cell contents. One way to implement the validation at the grid level is to handle the CurrentCellChanged event, and if the previous cell’s value is not proper, then return to that cell. You can download a sample that implements this process. The sample only handles the validation from cell to cell movement. If you want to handle the validation when the user clicks on the forms Close button, then you would have to add a special event handler for this and do one last validation at this point.

How do I implement custom column sorting in a listview

You create a class the implements the IComparer interface. This interface has a single method that accepts two objects, and returns positive integers if the first object is larger than the second, negative integers if the first object is less than the second object, and returns zero if they are the same. Once you have this class, then you handle the listview’s ColumnClick event to set the property ListViewItemSorter to point to an instance of this class. You can download a sample project. Here are some snippets. public class SorterClass : IComparer { private int _colNum = 0; public SorterClass(int colNum) { _colNum = colNum; } //this routine should return -1 if xy and 0 if x==y. // for our sample we’ll just use string comparison public int Compare(object x, object y) { System.Windows.Forms.ListViewItem item1 = (System.Windows.Forms.ListViewItem) x; System.Windows.Forms.ListViewItem item2 = (System.Windows.Forms.ListViewItem) y; if(int.Parse(item1.SubItems[_colNum].Text) < int.Parse(item2.SubItems[_colNum].Text)) return -1; else if(int.Parse(item1.SubItems[_colNum].Text) > int.Parse(item2.SubItems[_colNum].Text)) return 1; else return 0; } } //usage… private void listView1_ColumnClick(object sender, System.Windows.Forms.ColumnClickEventArgs e) { //don’t sort col 0 if(e.Column > 0) { SorterClass sc = new SorterClass(e.Column); listView1.ListViewItemSorter = sc; } }

How can I restrict the keystrokes that will be accepted in a column of my datagrid

You can create a custom column style and handle the KeyPress event of its TextBox member. Below is the code showing how this might be done. You can also download a sample project (C#, VB) that shows an implementation of this idea. public class DataGridDigitsTextBoxColumn : DataGridTextBoxColumn { public DataGridDigitsTextBoxColumn(System.ComponentModel.PropertyDescriptor pd, string format, bool b) : base(pd, format, b) { this.TextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(HandleKeyPress); } private void HandleKeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) { //ignore if not digit or control key if(!char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar)) e.Handled = true; //ignore if more than 3 digits if(this.TextBox.Text.Length >= 3 && !char.IsControl(e.KeyChar)) e.Handled = true; } protected override void Dispose(bool disposing) { if(disposing) this.TextBox.KeyPress -= new System.Windows.Forms.KeyPressEventHandler(HandleKeyPress); base.Dispose(disposing); } }

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);