public void buildReadOnlyDataGridView(DataGridView dataGridView, DataTable dataTable, LookupTables lookupTables) { DataTable newDataTable = new DataTable(dataTable.TableName); System.Collections.Generic.List<DataColumn> pKeys = new System.Collections.Generic.List<DataColumn>(); // Clear the DGV columns and set the autogenerate columns property... dataGridView.Columns.Clear(); dataGridView.AutoGenerateColumns = true; // First build the columns of the new table... foreach (DataColumn dataColumn in dataTable.Columns) { string newColumnName = dataColumn.ColumnName; newDataTable.Columns.Add(dataColumn.ColumnName); // Set the column header... newDataTable.Columns[newColumnName].Caption = GetFriendlyFieldName(dataColumn, dataColumn.ColumnName); // Add the extended properties from the source table... foreach (string key in dataColumn.ExtendedProperties.Keys) { newDataTable.Columns[newColumnName].ExtendedProperties.Add(key, dataColumn.ExtendedProperties[key]); } // Add this column to the primary keys list if extended properties indicate it is a primary key column if (newDataTable.Columns[newColumnName].ExtendedProperties.Contains("is_primary_key") && newDataTable.Columns[newColumnName].ExtendedProperties["is_primary_key"].ToString() == "Y") { pKeys.Add(newDataTable.Columns[newColumnName]); } if (dataColumn.ExtendedProperties.Contains("gui_hint")) { switch (dataColumn.ExtendedProperties["gui_hint"].ToString()) { case "LARGE_SINGLE_SELECT_CONTROL": break; case "SMALL_SINGLE_SELECT_CONTROL": break; default: // This column is not a Code/Value or FK lookup column, so set the datatype for the column (to facilitate sorting)... newDataTable.Columns[newColumnName].DataType = dataColumn.DataType; if(dataColumn.DataType == typeof(DateTime)) { newDataTable.Columns[newColumnName].DateTimeMode = DataSetDateTime.Unspecified; } break; } } // Set the readonly property... newDataTable.Columns[newColumnName].ReadOnly = dataColumn.ReadOnly; } // Set the datatable's primary key... newDataTable.PrimaryKey = pKeys.ToArray(); // Before populating the rows in the table, pre-load the FKey LU dictionaries with all needed values... foreach (DataColumn dc in dataTable.Columns) { if (lookupTables.IsValidFKField(dc)) { string lookupTable = dc.ExtendedProperties["foreign_key_dataview_name"].ToString(); int[] fkeys = new int[dataTable.Rows.Count]; // Build the list of FKeys that need to be resolved in the dicitonary... for(int i=0; i<dataTable.Rows.Count; i++) { //fkeys[i] = (int)dataTable.Rows[i][dc]; int fkey = 0; if(int.TryParse(dataTable.Rows[i][dc].ToString(), out fkey)) { fkeys[i] = fkey; } } lookupTables.PreLoadPKeyLUTDictionary(lookupTable, fkeys); } } // Now populate the rows of the new table... foreach (DataRow dr in dataTable.Rows) { if (dr.RowState != DataRowState.Deleted && dr.RowState != DataRowState.Detached) { DataRow newDataRow = newDataTable.NewRow(); foreach (DataColumn dc in newDataTable.Columns) { if (lookupTables.IsValidFKField(dc)) { string lookupTable = dc.ExtendedProperties["foreign_key_dataview_name"].ToString(); if (dr[dc.ColumnName] != DBNull.Value) { //newDataRow[dc.ColumnName] = lookupTables.GetDisplayMember(lookupTable, dr[dc.ColumnName].ToString(), "", dr[dc.ColumnName].ToString()); newDataRow[dc.ColumnName] = lookupTables.GetPKeyDisplayMember(lookupTable, (int)dr[dc.ColumnName], dr[dc.ColumnName].ToString()); } } else if (lookupTables.IsValidCodeValueField(dc)) { if (dr[dc.ColumnName] != DBNull.Value) { //newDataRow[dc.ColumnName] = lookupTables.GetDisplayMember("code_value_lookup", dr[dc.ColumnName].ToString(), "group_name='" + dc.ExtendedProperties["group_name"].ToString() + "'", dr[dc.ColumnName].ToString()); newDataRow[dc.ColumnName] = lookupTables.GetCodeValueDisplayMember(dc.ExtendedProperties["group_name"].ToString() + dr[dc.ColumnName].ToString(), dr[dc.ColumnName].ToString()); } } else { if (!string.IsNullOrEmpty(dr[dc.ColumnName].ToString())) { newDataRow[dc.ColumnName] = dr[dc.ColumnName].ToString(); if (dc.DataType == typeof(DateTime)) { if ("created_date modified_date owned_date".Contains(dc.ColumnName)) { // If the date field is created_date, modified_date, or owned_date it is stored in the database // as a UTC datetime by the middle tier. When the datetime field is sent to the CT it has a DateTimeMode property of // "DataSetDateTime.Unspecified". So convert the datetime to LocalTime using the ToLocalTime() method call... newDataRow[dc.ColumnName] = ((DateTime)dr[dc.ColumnName]).ToLocalTime(); //DateTime raw = (DateTime)dr[dc.ColumnName]; //DateTime local = ((DateTime)dr[dc.ColumnName]).ToLocalTime(); //DateTime utc = ((DateTime)dr[dc.ColumnName]).ToUniversalTime(); } } } } } // Add the row to the new data table... newDataTable.Rows.Add(newDataRow.ItemArray); } } // Set the sort and filter properties in the new datatable... newDataTable.DefaultView.Sort = dataTable.DefaultView.Sort; newDataTable.DefaultView.RowFilter = dataTable.DefaultView.RowFilter; newDataTable.DefaultView.AllowDelete = false; newDataTable.DefaultView.AllowEdit = false; newDataTable.DefaultView.AllowNew = false; // Bind the DataGridView to the datasource passed into this procedure... newDataTable.AcceptChanges(); // NOTE: Sometimes the datagridview's datasource is actually a bindingsource (to wire up the binding navigator) // so binding must be handled differently... if (dataGridView != null && dataGridView.DataSource != null && dataGridView.DataSource.GetType() == typeof(BindingSource)) { // Bind the new table to the default binding source (the bindingNavigator and mainDGV are both bound to this bindingSource)... ((BindingSource)dataGridView.DataSource).DataSource = newDataTable; } else { dataGridView.DataSource = newDataTable; } foreach (DataGridViewColumn dgvc in dataGridView.Columns) { // Turn on wrap mode for all columns set as varchar(max) and set the gridview column text... if (newDataTable.Columns[dgvc.Name].ExtendedProperties.Contains("max_length") && newDataTable.Columns[dgvc.Name].ExtendedProperties["max_length"].ToString().Trim() == "-1") { dgvc.DefaultCellStyle.WrapMode = DataGridViewTriState.True; } // Get the text for the column header... dgvc.HeaderText = GetFriendlyFieldName(newDataTable.Columns[dgvc.Name], newDataTable.Columns[dgvc.Name].ColumnName); // Get the text for the column description... if (newDataTable.Columns[dgvc.Name].ExtendedProperties.Contains("description") && !string.IsNullOrEmpty(newDataTable.Columns[dgvc.Name].ExtendedProperties["description"].ToString())) { dgvc.ToolTipText = newDataTable.Columns[dgvc.Name].ExtendedProperties["description"].ToString(); } } }