I want to create a datagridview in C# (winform) with a variable number of columns. I have done this
dataGridView2 = _dm.CreateGrid();
where CreateGrid() is the following method:
public DataGridView CreateGrid()
{
DataGridView dtgr = new DataGridView();
using (DbEntities db = new DbEntities())
{
foreach (Resource r in db.Resources)
{
DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn();
col.ValueType = typeof(string);
col.Name = r.Description;
col.HeaderText = r.Description;
col.DataPropertyName = r.Description;
dtgr.Columns.Add(col);
}
}
return dtgr;
}
Description is of type string. I don't see the datagridview in my winform. Where is the problem ?
I think DataGridViewTextBoxColumn is causing the problem. Try using DataGridViewColumn instead. Hope that helps.
You need add your DataGridView to controls of the Form
dataGridView2 = _dm.CreateGrid();
this.Controls.Add(dataGridView2);
Why you create columns manually. DataGridView will generate columns automatically based on the columns/fields of the datasource, if you set AutoGenerateColumns = true
From MSDN DataGridView.AutoGenerateColumns Property
Related
I want to create a DataGridview to load few records after user performs a search in database once user clicks on row it should show all records in TextBoxes.
I have more than 20 TextBoxes and few Comboboxes and a DateTimePicker but I just want to show few columns in the DataGridView.
I know how to load data into a DataGridView on form load, but on search or on row click select all DataGridView Column into TextBoxes I am stuck.
Per your comment, here is how to change data on row changing in a datagridview. you will need to alter this to make the actual database calls. I made a small table for example purposes. For this to work, make a new winforms application, put a DataGridView on it and 2 textboxes
using System.Data;
using System.Linq;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
DataTable PretendImADataBase;
public Form1()
{
InitializeComponent();
PretendImADataBase = CreateTestData();
//this assigns the row enter event to this function. Each time the row changes,
//the function is called. Inside this function, you load your "big data" columns.
//That way, you only load 2 or 3 columns for all rows, and each time the row changes,
//you go back out and load all of the details for only that 1 row.
//Pretty basic way to load data..
dataGridView1.RowEnter += dataGridView1_RowEnter;
//initial loading, only 1 or 2 columns of large dataset, to keep loading time fast.
//primary key, and enough info to identify the full record.
dataGridView1.DataSource = CreateDataSource1();
}
private void dataGridView1_RowEnter(object sender, DataGridViewCellEventArgs e)
{
//This is where you would make your database call to load big data.
var x = sender as DataGridView;
if (x.DataSource == null) return;
var id = x[0, e.RowIndex].Value;
DataRow oRow = (from DataRow row in PretendImADataBase.Rows where (int)row["FK"] == (int)id select row).FirstOrDefault();
if (!(oRow == null))
{
textBox1.Text = oRow[3].ToString();
textBox2.Text = oRow[4].ToString();
}
}
private DataTable CreateTestData()
{
DataTable oDt = new DataTable();
DataColumn oCol = new DataColumn("ID", typeof(int));
oDt.Columns.Add(oCol);
oCol = new DataColumn("FK", typeof(int));
oDt.Columns.Add(oCol);
oCol = new DataColumn("Data1", typeof(string));
oDt.Columns.Add(oCol);
oCol = new DataColumn("Data2", typeof(string));
oDt.Columns.Add(oCol);
DataRow oRow = oDt.NewRow();
oRow["ID"] = 1;
oRow["FK"] = 1;
oRow["Data1"] = "Test Data 1";
oRow["Data2"] = "Test Data 2";
oDt.Rows.Add(oRow);
oRow = oDt.NewRow();
oRow["ID"] = 2;
oRow["FK"] = 2;
oRow["Data1"] = "Test Data 3";
oRow["Data2"] = "Test Data 4";
oDt.Rows.Add(oRow);
return oDt;
}
private DataTable CreateDataSource1()
{
DataTable oDt = new DataTable();
DataColumn oCol = new DataColumn("ID",typeof(int));
oDt.Columns.Add(oCol);
oCol = new DataColumn("Display", typeof(string));
oDt.Columns.Add(oCol);
DataRow oRow = oDt.NewRow();
oRow["ID"] = 1;
oRow["Display"] = "Test 1";
oDt.Rows.Add(oRow);
oRow = oDt.NewRow();
oRow["ID"] = 2;
oRow["Display"] = "Test 2";
oDt.Rows.Add(oRow);
return oDt;
}
}
}
Not really sure if I get what you want but, you are using the datasource of the datagridview to bind the results, right? if so, after you selected the datasourse, you can hide the columns you dont want to show, like this:
DataGridView dgv = new DataGridView();
dgv.DataSource = YourDataTable;
// hide the columns you dont want on grid
dgv.Columns[0].Visible = false;
dgv.Columns[2].Visible = false;
dgv.Columns[3].Visible = false;
dgv.Columns[4].Visible = false;
This way your grid will show only the columns you want, but when the click event triggers you can access the hidden columns to show them on your controls.
You can do this simple task.
You have to add all the columns in your GridView as the text fields you have on your form.
You can set the Visible property of the column to true that you want to show otherwise you can hide by setting this property to false.
Now, you will be able to fill the row data to the relevant fields on the form using CellDoubleClick or CellClick or RowDoubleClick or RowClick events.
You have to set the property of grid view AutoGenerateColumns to False and the name of each data table column name is to map with grid view columns using DataGridViewProperty.
I am reading an xml file using dataset and then i am creating a datagridview and assigning the table from dataset to datagridview.datasource dynamically.
The problem i am facing here is, i want to add a combobox for one cell in datagridview.
Below is my code :
datagridview1.AllowUserToAddRows = false;
datagridview1.AllowUserToDeleteRows = false;
datagridview1.RowHeadersVisible = false;
datagridview1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
datagridview1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
datagridview1.DataMember = "";
datagridview1.DataSource = my_dataTable;
datagridview1.Columns["first name"].ReadOnly = true;
datagridview1.Columns["Second name"].Visible = false;
datagridview1.Columns["place"].Visible = false;
datagridview1.Columns["address"].Visible = false;
string[] datasource = { "add1", "add2" };
DataGridViewComboBoxCell combo = new DataGridViewComboBoxCell();
combo.DataSource = datasource;
datagridview1.Rows[2].Cells[2] = combo;
It is giving me datagridviewcomboboxcell value is not valid error.If i give some value then it runs well but not able to see the combobox in datagridview.
You can use the DataSource to feed to Items, but using a simple string array will not work.
Instead you can convert the array to a List<string> :
string[] datasource = { "add1", "add2" };
DataGridViewComboBoxCell combo = new DataGridViewComboBoxCell();
combo.DataSource = datasource.ToList();
DGV.Rows[2].Cells[2] = combo;
To set a value you can use..
combo.Value = combo.Items[0];
..after having set the cell.
For better control, especially for having spearate Display- and ValueMembers you can switch to a Dictionary or use a List<someClass>..
Here is my code:
DataSet data = new DataSet();
data.ReadXml("data.xml");
DataGridView grid = new DataGridView();
var genreCboBoxItems = data.Tables[0].AsEnumerable().Select(genre => genre.Field<string>("genre")).Distinct().ToArray();
// TODO: Make is so the 'genre' column in grid is a combo box?
grid.DataSource = data.Tables[0];
grid.Dock = DockStyle.Fill;
this.Controls.Add(grid);
*edit: genreCboBoxItems
Try this: (not tested)
var column = new DataGridViewComboBoxColumn();
column.DataSource = data.Tables[0].AsEnumerable().
Select(genre => new { genre = genre.Field<string>("genre") }).Distinct();
column.DataPropertyName = "genre";
column.DisplayMember = "genre";
column.ValueMember = "genre";
grid.DataSource = data.Tables[0];
// Instead of the below line, You could use grid.Columns["genre"].Visible = false;
grid.Columns.Remove("genre");
grid.Columns.Add(column);
This might help you cast DataGridViewColumn to DataGridViewComboBox.
First create DataGridViewComboBoxColumn using designer with proper name. Then say you have a list of String list and other string values to bind to that datagridview then use this code:
Below code will bind a list to two DataGridViewTextBoxCell and a DataGridViewComboBoxCell. Note AllCriterias is a list with two string values and a list of string. DGVEligibilityCriteria is the grid name.
for (int i = 0; i < AllCriterias.Count; i++)
{
DataGridViewTextBoxCell Cmb1 = (DataGridViewTextBoxCell)DGVEligibilityCriteria.Rows[i].Cells[0];
Cmb1.Value = AllCriterias[i].Name;
DataGridViewTextBoxCell Cmb2 = (DataGridViewTextBoxCell)DGVEligibilityCriteria.Rows[i].Cells[1];
Cmb2.Value = AllCriterias[i].Type;
DataGridViewComboBoxCell Cmb = (DataGridViewComboBoxCell)DGVEligibilityCriteria.Rows[i].Cells[2];
foreach (var filtervalue in AllCriterias[i].FilterValues)
{
Cmb.Items.Add(filtervalue);
}
}
Need to display the fist index as default by setting selectindex property.
Use this code : Here "filterValues" is the name of the DataGridViewComboBoxCell which u created in the datagridview designer.
foreach (DataGridViewRow row in DGVEligibilityCriteria.Rows)
{
row.Cells["filterValues"].Value = (row.Cells["filterValues"] as DataGridViewComboBoxCell).Items[0];
}
I have a DataGridView and I'm binding it to a BindingList<KeyValuePair<string, float>>. Here's the relevant part of the code:
dgv.AutoGenerateColumns = false;
DataGridViewTextBoxColumn firstColumn = new DataGridViewTextBoxColumn();
firstColumn.DataPropertyName = "Key";
firstColumn.HeaderText = "First Column";
DataGridViewTextBoxColumn secondColumn = new DataGridViewTextBoxColumn();
secondColumn.DataPropertyName = "Value";
secondColumn.HeaderText = "Second Column";
secondColumn.ReadOnly = false;
secondColumn.ValueType = typeof(float);
dgv.Columns.Add(firstColumn);
dgv.Columns.Add(secondColumn);
dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dgv.MultiSelect = false;
dgv.EditMode = DataGridViewEditMode.EditOnKeystrokeOrF2;
dgv.ReadOnly = false;
_bindingList = new BindingList<KeyValuePair<string, float>>(_someList);
dgv.DataSource = _bindingList;
But the second column is still not editable. What should I do to make the second column editable and the first one not?
Edit: I'd like the changes to be reflected on the BindingList instance itself.
Edit 2: I have added this line in the end of the code and now I'm getting an error:
dgv.Columns[1].ReadOnly = false;
I get this error:
DataGridView column bound to a read-only field must have ReadOnly set to True.
Edit 3: The problem seems to be that I'm using KeyValuePairs in my list.
The problem turns out to be that the Key and Value properties of the KeyValuePair class are read-only. The solution is to create a new class that has public setters to represent the data.
I have a DataGridView where I set the DataSource to a collection of objects when the tab the DataGridView resides is selected.
After the datasource is set I'd like to change the "County" column to a DataGridViewComboBoxColumn with the state's counties as the items. Nothing I've seen works yet - it always gives an exception.
Is there a way to change the column type without deleting it?
Is there a way to have a combobox or other control appear when I click on a cell in that row without having to modify the column type?
======================== My Failing Code ========================
//ii is a for loop variable on the dataGridViewFields.Columns.Count
string colName = dataGridViewFields.Columns[ii].Name;
if (colName.Equals("County"))
{
string dpName = dataGridViewFields.Columns[ii].DataPropertyName;
DataGridViewComboBoxColumn column = new DataGridViewComboBoxColumn();
//get current column characteristics.
column.ValueType = dataGridViewFields.Columns[ii].ValueType; ;
column.Name = dataGridViewFields.Columns[ii].Name;
column.HeaderText = dataGridViewFields.Columns[ii].HeaderText;
column.Width = dataGridViewFields.Columns[ii].Width;
//remove column from grid
dataGridViewFields.Columns.RemoveAt(ii);
//set column combobox characteristics
column.DropDownWidth = 160;
column.MaxDropDownItems = 10;
column.Items.AddRange(new string[] {"Dane", "Dodge", "Door"});
column.FlatStyle = FlatStyle.Flat;
DataGridViewCell cell = new DataGridViewComboBoxCell();
cell.Style.BackColor = Color.Wheat;
cell.ValueType = typeof(string);
cell.Value = "Door";
column.CellTemplate = cell;
//add to the grid.
dataGridViewFields.Columns.Insert(ii, column);
dataGridViewFields.Columns[ii].DataPropertyName = dpName;
//dataGridViewFields.EditMode = DataGridViewEditMode.EditProgrammatically;
}
I think you would be interested in the DisplayStyle of the ComboBox Column
Set DisplayStyle to Nothing. This will make the ComboBox appear only when you try to Edit the cell