How can I bind two datagrids in a Master-Detail relationship?

Please download this sample before reading the rest of this FAQ. Looking through the sample will help follow the description. simpledata2.zip What this boils down to is this: 1) Load both Master and Details queries in a dataset. // I am using the SQL server NorthWind database this.dataAdapterMaster.Fill(this.dataSet, ”Customers”); this.dataAdapterDetails.Fill(this.dataSet, ”Orders”); 2) Bind the master data grid to the Master dataset table. // The master view grid.DataSource = this.dataSet; grid.DataMember = ”Customers”; 3) Create a relationship that describes how the two tables relate to each other. A primary key foreign key relationship is defined by two attributes. The primary key column in the master table The foreign key column in the details table The created relationship is added to the dataset. this.dataSet.Relations.Add(”CustomersToOrders”, dataSet.Tables[”Customers”].Columns[”CustomerID”], dataSet.Tables[”Orders”].Columns[”CustomerID”]); 4) Set the data member for the details table to be the name of relationship that was added to the dataset. // The name of the relation is to be used as the DataMember for the // details view details.DataSource = this.dataSet; // use the relationship called ”CustomersToOrders in the Customers table. // Remember that we called the relationship ”CustomersToOrders”. details.DataMember = ”Customers.CustomersToOrders”;

How can I bind the datagrid to a datasource without using any wizards?

Here is a really simple data binding sample. Just drag and drop a datagrid onto a default Windows Forms application. Follow the steps below to bind this grid to the NorthWind db in SQL server. Complete Sample: simpledata.zip // Create a connection SqlConnection connection = new SqlConnection(this.GetConnectionString()); // Create a data adapter. Think of the data adapter as an object that knows how to get the data from the // data source into a dataset SqlDataAdapter dataAdapter = new SqlDataAdapter(this.GetCommandText(), connection); // fill the dataset using the data adapter DataSet dataSet = new DataSet(”Customers”); dataAdapter.Fill(this.dataSet, ”Customers”); // bind to the grid grid.DataSource = this.dataSet; // the big picture grid.DataMember = ”Customers”; // the specific table that we want to bind to // The connection text looks like this // If your SQL server is running on the default port, you can remove the port attribute. private string GetConnectionString() { string server = ”your_server_name”; string serverPort = ”port_address”; string catalog = ”NorthWind”; string password = ”user_pass”; string userId = ”user_name”; string connectionString = ”data source={0},{1};initial catalog={2};” + ”password={3}; user id={4}; packet size=4096”; return string.Format(connectionString, server, serverPort, catalog, password, userId); } // The command text looks like this private string GetCommandText() { string commandText = ”Select * from customers”; return commandText; }

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