Setting DataPropertyName in DataGridViewComboBoxColumn from BindingSource - c#

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

How to get value of a programmatically written combobox in a datagrid in wpf?

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.

DataGridView bound to BindingList shows too many columns

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;

how to add a combo box in a datagrid view for only one cell dynamically

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>..

C# Windowsform updating dynamic generated combobox

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.

How to set a DataGridView column to a DataGridViewComboBoxColumn?

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

Categories

Resources