I have a problem with setting a correct data property for DataPropertyName of DataGridViewComboBoxColumn. I have a BindingSource and I set its DataSource to BindingList of custom objects. These objects have properties which I'd like to assign as columns in DataGridView (pluginsDataGrid):
var source = new BindingSource {DataSource = _plugins};
pluginsDataGrid.AutoGenerateColumns = false;
pluginsDataGrid.DataSource = source;
Everything's fine when I have a simple string as a property - it is Name:
using (var nameCol = new DataGridViewTextBoxColumn())
{
nameCol.DataPropertyName = "Name";
nameCol.Name = "Name";
pluginsDataGrid.Columns.Add(nameCol);
}
but I don't know how to set DataGridViewComboBoxColumn options. I gave it a try this way:
using (var depCol = new DataGridViewComboBoxColumn())
{
depCol.DataPropertyName = "Dependencies";
depCol.Name = "Dependencies";
pluginsDataGrid.Columns.Add(depCol);
}
where Dependencies is a list of strings. But it is not working. What kind of property should be assign to it?
You need to specify DataSource for the column, example:
comboboxColumn.DataSource = collection;
comboboxColumn.ValueMember = ColumnName;
comboboxColumn.DisplayMember = ValueMember;
In your case use DataBindingComplete event to psecify collection:
void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
DataGridViewComboBoxCell comboCell = (DataGridViewComboBoxCell)dataGridView1.Rows[i].Cells["Dependencies"];
[Plugin_Type] entry = dataGridView1.Rows[i].DataBoundItem as [Plugin_Type];
comboCell.DataSource = entry.[YOUR_PROPERTY];
}
}
Related
To follow my previous post here => Binding SelectedItem of ComboBox in DataGrid with different type
I have now a datagrid containing 2 columns, one with a text, the other with a combobox (in a datatemplate, written thru the C# code, not the Xaml).
After having done some choice on the combobox, I now would like to parse the result but the value of the cell containing my combobox stay empty :
foreach(DataRowView row in Datagrid1.Items)
{
var firstColumNresult = row.Row.ItemArray[0];// Return correctly a string
var myrow = row.Row.ItemArray[1];// always empty...
}
The result is that I cant get the values of my (previously generated) combobox.
I suppose one binding must missed somewhere...
This is the combobox creation code :
DataTable tableForDG = new DataTable();
tableForDG.Columns.Add(new DataColumn { ColumnName = "Name", Caption = "Name" });
tableForDG.Columns.Add(new DataColumn { ColumnName = "Attachment", Caption = "Attachment" }); // this column will be replaced
tableForDG.Columns.Add(new DataColumn { ColumnName = "AttachmentValue", Caption = "AttachmentValue" });
tableForDG.Columns.Add(new DataColumn { ColumnName = "DisplayCombo", Caption = "DisplayCombo", DataType=bool });
// Populate dataview
DataView myDataview = new DataView(tableForDG);
foreach (var value in listResults)// a list of string
{
DataRowView drv = myDataview.AddNew();
drv["Name"] = value.Name;
drv["Attachment"] = value.Name;// this column will be replaced...
drv["DisplayCombo"] = true;// but it can be false on my code...
}
var DG = myDataview;//
Datagrid1.ItemsSource = DG;
Datagrid1.AutoGenerateColumns = true;
Datagrid1.Items.Refresh();
DataGridTemplateColumn dgTemplateColumn = new DataGridTemplateColumn();
dgTemplateColumn.Header = "Attachment";
var newCombobox = new FrameworkElementFactory(typeof(ComboBox));
newCombobox.SetValue(ComboBox.NameProperty, "myCBB");
Binding enableBinding = new Binding();
newCombobox.SetValue(ComboBox.IsEnabledProperty, new Binding("DisplayCombo"));
newCombobox.SetValue(ComboBox.SelectedValueProperty, new Binding("AttachmentValue"));
List<string> listUnitAlreadyAttached = new List<string>();
// fill the list...
enableBinding.Source = listUnitAlreadyAttached;
newCombobox.SetBinding(ComboBox.ItemsSourceProperty, enableBinding);
var dataTplT = new DataTemplate();
dataTplT.VisualTree = newCombobox;
dgTemplateColumn.CellTemplate = dataTplT;
Datagrid1.Columns[1] = dgTemplateColumn;
Any idea/advice ?
You should explicitely specify the binding mode and update trigger of your binding. Also use SetBinding instead of SetValue:
var valueBinding = new Binding("AttachmentValue")
{
Mode = BindingMode.TwoWay,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
};
newCombobox.SetBinding(ComboBox.SelectedValueProperty, valueBinding);
This should enable you to get the selected value into your row data. It might not update in the displayed datagrid value for the AttachmentValue column.
I've got a class with two public properties, Name and Text. I want to bind a DataGridView to a list of these objects, so I loaded them into a BindingList<>. I only want to show the Name property in the DataGridView, but I'm getting both columns. What am I doing wrong?
private void fileOpenTextBox1_FileSelected(object sender, string e)
{
m_definitions = new BindingList<TagSimDefinition>(TagSimDefinition.Read(e));
dgvTagNames.AutoGenerateColumns = false;
dgvTagNames.Columns.Clear();
DataGridViewCell cell = new DataGridViewTextBoxCell();
DataGridViewTextBoxColumn colTagName = new DataGridViewTextBoxColumn()
{
CellTemplate = cell,
Name = "colTagName",
HeaderText = "Tag Name",
DataPropertyName = "Name"
};
dgvTagNames.Columns.Add(colTagName);
dgvTagNames.DataSource = m_definitions;
}
#Robert you are setting,
dgvTagNames.DataSource = m_definitions;
for that it is showing both columns. If you want to get one column use it like this,
m_definitions = new BindingList<TagSimDefinition>(TagSimDefinition.Read(e));
dgvTagNames.AutoGenerateColumns = false;
dgvTagNames.Columns.Clear();
dgvTagNames.ColumnCount = 1;
dgvTagNames.Columns[0].Name = "colTagName";
dgvTagNames.Columns[0].DataPropertyName = "colTagName";
dgvTagNames.DataSource = m_definitions;
Another solution:
m_definitions = new BindingList<TagSimDefinition>(TagSimDefinition.Read(e));
dgvTagNames.Columns.Clear();
DataGridViewCell cell = new DataGridViewTextBoxCell();
DataGridViewTextBoxColumn colTagName = new DataGridViewTextBoxColumn()
{
CellTemplate = cell,
Name = "colTagName",
HeaderText = "Tag Name",
DataPropertyName = "Name"
};
dgvTagNames.Columns.Add(colTagName);
dgvRegion.Rows.Clear();
int index = 0;
foreach (var dparam in m_definitions)
{
dgvTagNames.Rows.Add();
dgvTagNames["colTagName", index].Value = dparam.<Property1>;
dgvTagNames.Rows[index].Tag = dparam;
index++;
}
Everyone here is making things wayyyyyyy to complicated. If you have columns you don't want displayed you could just set the Column.Visible = false after the setting the datasource.
dgvTagNames.Columns[index].Visible = false;
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>..
I think I am overseeing something.
I dynamically generate a few ComboBoxes with this code (I do the same for other controls like TextBox, Label etc)
private ComboBox addControlsComboBox(string Id, string TBName, int point_X, int point_Y, int SizeWidth, DataTable DT)
{
ComboBox combobox = new ComboBox();
combobox.Text = TBName;
combobox.Location = new Point(point_X, point_Y);
combobox.Size = new Size(SizeWidth, 20);
combobox.Name = Id + TBName;
combobox.DataSource = DT;
combobox.DisplayMember = "key";
combobox.ValueMember = "value";
combobox.Enabled = true;
return combobox;
}
When I automatically want to set the selected value, for the controls all the values are set correct except for the ComboBox. Not 1 comboBox is updated but all the ComboBoxes.
I use a nested dictionary object to store all the values that i need to match.
See part of the used update Code
foreach (Control gb in GroupPanel.Controls)
{
foreach (Control childc in gb.Controls)
{
if (DataCollection[GroupNames].ContainsKey(childc.Name))
{
KeyName = childc.Name;
numberLessKeyName = SL.RemoveDigits(childc.Name);
TextValue = DataCollection[GroupNames][KeyName];
switch (NumberLessKeyName)
{
case "Name":
int IntTextValue = Convert.ToInt32(TextValue);
TextValue = IntTextValue.ToString("d2");
break;
}
switch (childc.GetType().ToString())
{
case "System.Windows.Forms.TextBox":
childc.Text = TextValue;
break;
case "System.Windows.Forms.ComboBox":
// Not Working
ComboBox combobox = (ComboBox)childc;
combobox.SelectedValue = TextValue;
//Also not Working
// --> childc.Text = TextValue;
break;
case "System.Windows.Forms.CheckBox":
CheckBox chChildc = (CheckBox)childc;
if (TextValue == "Yes")
{
chChildc.Checked = true;
}
break;
};
}
}
}
What I am doing wrong?
Can somebody help me please?
[EDIT 1]
Thanks to Karol
I added The Following Lines + interface ICloneable and it worked. Many Thanks.
DataTable DT = new DataTable();
DT = DTAttribute;
DataTable DTClone = (DataTable)DT.Clone();
For those searching [C# Object Clone Wars][1] link
[EDIT 2]
A other Idea is to use COPY (works also)
DataTable DT = new DataTable();
DT = DTAttribute;
DataTable DTClone = DT.Copy();
I think You bind all ComboBox same DataTable.
You must have diffrent instance of DataTable for each ComboBox. You can do this in two ways:
- Once again SELECT data from database.
- Use deep copy to make new instance of DataTable.
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];
}