Combobox - setting datasource clears Items - c#

I have a routine that populates a combobox from a database; the first time the combo is populated, it all works perfectly, but if I try to do it again, the combobox is completely blank. I narrowed it down to this line:
cboThis.DataSource = cboThis.Items;
This seems to clear the Items collection for the combobox...but only if the combo was already populated.
Any ideas what could be going on here?
There IS an event handler for one of the combo's SelectedIndexChanged event, but this doesn't seem to get called by anything but the first and last lines of code.
Here's the complete routine:
public void ComboFromDB(ComboBox cboThis, string strTable, string strField)
{
cboThis.SelectedIndex = -1;
cboThis.DataSource = null;
cboThis.Items.Clear();
string strQuery = #"SELECT ID, " + strField + " FROM " + strTable;
using (SqlConnection sqcConnection = new SqlConnection(strConnection))
{
sqcConnection.Open();
SqlCommand sqcCommand = new SqlCommand(strQuery, sqcConnection);
SqlDataReader dr = sqcCommand.ExecuteReader();
while (dr.Read())
{
cboThis.Items.Add(new ComboItem((int)dr[0], dr[1].ToString())); //this all works fine
}
}
cboThis.DataSource = cboThis.Items; //This line clears cboThis.Items...
cboThis.ValueMember = "ID";
cboThis.DisplayMember = "Display";
cboThis.SelectedIndex = -1;
}
Cheers

try to create a structure like this
struct tmpItems
{
//member variables
private Int32 _ID;
private String _Display;
//properties
public Int32 ID
{
get {return _ID;}
}
public String Display
{
get {return _Display;}
}
public tmpItems(Int32 pID , String pDisplay)
{
_ID = pID;
_Display = pDisplay;
}
}
now assign
ArrayList dataItems = new ArrayList();
dataItems.Add(new tmpItems((int)dr[0], dr[1].ToString()));
then finally set
cbothis.DataSource = dataItems;
cboThis.ValueMember = "ID";
cboThis.DisplayMember = "Display";
Ensure that ComboBox SelectedIndexChange event handles the Initialization of data..
because while setting datasource , the items will be added one by one.. each time generating SelectedIndexChangeEvent .. but will find difficult in accessing SelectedValue property at this stage

In the end I binned using Items and just shoved it through a Dictionary.

Related

ListItem.Selected returning false

I have a listbox with a list of items that get loaded when you navigate to a certain page. Then I have an on click that passes parameters to an AddProducts method. That method is what loops through all selected items and inserts values from the fields filled in as well as takes the values from the listItems and adds them as parameters to a stored procedure.
The problem I'm running into is that when looping through the listItems
if(selectedItem.Selected) is returning false, but in my method where I load the listbox I initialize a SelectedValue so I'm not sure why it's giving me the error message I have for no selected items. I was able to get it to work yesterday before I moved LoadListBoxCategories outside of LoadAddData but unsure as to why that would have any effect to if(listItem.Selected).
I'm relatively new to asp.net so any help/ explanation as to why my code isn't working is extremely appreciated. I've spent the last three days trying to figure this out and haven't found a solution that works.
Code:
Page_Load:
protected void Page_Load(object sender, EventArgs e)
{
if (Session[IS_LOGGED_IN] == null)
{
Response.Redirect("/utilities/companydata/login.aspx", true);
return;
}
gvTextInputs.RowEditing += new GridViewEditEventHandler(gvTextInputs_RowEditing);
if (!IsPostBack)
{
string pageId = Request.QueryString["pageid"];
string productId = Request.QueryString["productid"];
/* Add Mode */
if (!string.IsNullOrEmpty(pageId))
{
SetMode(MODE_ADD, "");
LoadAddData(pageId);
LoadListBoxCategories(pageId);
}
else if (!string.IsNullOrEmpty(productId))
{
string imageServer;
if (LoadProductData(productId, out imageServer))
{
InitImageGridview();
InitTextGridview();
InitStaticGridview();
SetMode(MODE_EDIT, imageServer);
SetImageServer(imageServer);
}
else
{
//TO DO - Return Error
}
}
}
else
{
InitImageGridview();
InitTextGridview();
InitStaticGridview();
}
}
Load ListBox:
private void LoadListBoxCategories(string pageId)
{
listBoxCategories.Visible = true;
//This gets query is so I can store the CompanyId and the CombinedValue data from pageId
string select = "SELECT companyName, cl.GbsCompanyId, cl.companyId, wpt.productTypeId, productName, (CAST(wp.pageId as varchar(200)) +'|'+ CAST(wp.productTypeId as varchar(200)) + '|' ) AS CombinedValue FROM CompanyList cl, WtpPages wp, WtpProductTypes wpt WHERE cl.companyId=wp.companyId AND wpt.productTypeId=wp.productTypeId AND wp.pageId=#pageId";
SqlDataSource connectionId = new SqlDataSource(DB_CONNECT, select);
connectionId.SelectParameters.Add("pageId", pageId);
DataView dView = (DataView)connectionId.Select(DataSourceSelectArguments.Empty);
if (dView.Table.Rows.Count == 1)
{
string companyId = dView.Table.Rows[0]["companyId"].ToString();
string curCategoryProductTypeId = dView.Table.Rows[0]["CombinedValue"].ToString();
// EXEC MCAdmin_GetAllCategoriesByCompanyId #companyId
// Lists All Categories #companyId has Active
string selectLoadData = "EXEC MCAdmin_GetAllCategoriesByCompanyId #companyId";
SqlDataSource conn = new SqlDataSource(DB_CONNECT, selectLoadData);
conn.SelectParameters.Add("companyId", companyId);
lstCategoriesBox.Items.Clear();
lstCategoriesBox.Items.Add(new ListItem("--Select--", null));
lstCategoriesBox.DataTextField = "productName";
lstCategoriesBox.DataValueField = "CombinedValue";
// Pre-selects the value of the productTypeId you are trying to add a product for
// to send later run against a foreach insert in AddProduct()
lstCategoriesBox.SelectedValue = curCategoryProductTypeId;
testOutcomeCategory.InnerText = curCategoryProductTypeId;
lstCategoriesBox.DataSource = conn;
lstCategoriesBox.DataBind();
}
}
AddProduct:
private string AddProduct(string companyId, out string errMsg)
{
foreach (ListItem selectedItem in lstCategoriesBox.Items)
{
if (selectedItem.Selected)
{
// assign current productTypeId & pageId from selected Categories new CombinedValue column
string[] splitColumnValue = selectedItem.Value.Split('|');
string selectedPageId = splitColumnValue[0].ToString();
string selectedProductTypeId = splitColumnValue[1].ToString();
SqlDataSource connnection = new SqlDataSource(DB_CONNECT, "");
connnection.InsertCommand = "EXEC MCAdmin_AddProductFromClassic #pageId, #productTypeId, #productCode, #imgDirectory, #numSides, #sortOrder, #isActive, #template, #template2, #template3, #EditorJson, #MockupTemplateBase, #MockupTemplateTreatment, #BorderDefault ";
connnection.InsertParameters.Add("pageId", selectedPageId);
connnection.InsertParameters.Add("productTypeId", selectedProductTypeId);
connnection.InsertParameters.Add("productCode", txtProductCode.Text);
connnection.InsertParameters.Add("numSides", ddlNumSides.SelectedValue);
connnection.InsertParameters.Add("sortOrder", txtSortOrder.Text);
connnection.InsertParameters.Add("isActive", ddlActive.SelectedValue);
connnection.InsertParameters.Add("template", txtTemplate1.Text);
connnection.InsertParameters.Add("template2", txtTemplate2.Text);
connnection.InsertParameters.Add("template3", txtTemplate3.Text);
connnection.InsertParameters.Add("EditorJson", txtJson.Text);
connnection.InsertParameters.Add("MockupTemplateBase", txtMockupTemplateBase.Text);
connnection.InsertParameters.Add("MockupTemplateTreatment", txtMockupTemplateTreatment.Text);
connnection.InsertParameters.Add("BorderDefault", txtBorderDefault.Text);
/* Special Product Code for Upload Artwork Business Card */
if (txtProductCode.Text.ToUpper() == "BPFAH1-001-100")
{
connnection.InsertParameters.Add("imgDirectory", "/images/business-cards/general/");
}
else
{
connnection.InsertParameters.Add("imgDirectory", ddlImgDir.SelectedValue);
}
int result = connnection.Insert();
if (result > 0)
{
SqlDataSource connect = new SqlDataSource(DB_CONNECT, "");
connect.SelectCommand = "SELECT TOP 1 wtpProductId FROM WtpProducts ";
connect.SelectCommand = "WHERE productTypeId=#productTypeId AND pageId=#pageId DESC ";
connect.SelectParameters.Add("pageId", selectedPageId); //
connect.SelectParameters.Add("productTypeId", selectedProductTypeId); //
DataView dView = (DataView)connect.Select(DataSourceSelectArguments.Empty);
if (dView.Table.Rows.Count == 1)
{
string wtpProductId = dView.Table.Rows[0]["wtpProductId"].ToString();
errMsg = "";
return wtpProductId;
}
else
{
errMsg = "ERROR: Could not get productId of newly created Product.";
return "0";
}
}
else
{
errMsg = "ERROR: Could not add WtpProduct record to DB";
return "0";
}
}
else
{
errMsg = "ERROR: You must select a Category";
return "0";
}
}
errMsg = "ERROR: Did not make it into the foreach loop";
return "0";
}
OnClick method:
protected void OnClick_btnAddProduct(object sender, EventArgs e)
{
string pageId = Request.QueryString["pageid"];
testOutcomeCategory.InnerText = lstCategoriesBox.SelectedValue; // This proves that I have something selected!!!
string select = "SELECT companyName, cl.GbsCompanyId, cl.companyId, wpt.productTypeId, productName, baseImgDirectory, templateDirectory, wp.imageServer FROM CompanyList cl, WtpPages wp, WtpProductTypes wpt WHERE cl.companyId=wp.companyId AND wpt.productTypeId=wp.productTypeId AND wp.pageId=#pageId";
SqlDataSource conn = new SqlDataSource(DB_CONNECT, select);
conn.SelectParameters.Add("pageId", pageId);
DataView dView = (DataView)conn.Select(DataSourceSelectArguments.Empty);
if(dView.Table.Rows.Count == 1)
{
string companyId = dView.Table.Rows[0]["companyId"].ToString();
if (!string.IsNullOrEmpty(pageId))
{
string errMsg;
string productId = AddProduct(companyId, out errMsg);
if(productId != "0")
{
Response.Redirect("/utilities/companydata/add-edit-wtp-product.aspx?productid=" + productId, true);
SetStatusMsg("Success", false);
}
else
{
SetStatusMsg(errMsg, true);
}
}
}
}
The list box instance is recreated on the server-side during the postback (as well as entire page). You do not set the selected items in the Page_Load event handler - if (!IsPostBack) goes to else branch. This is why you don't see them.
Ok,
lstCategoriesBox.Items.Clear();
Ok, above goes nuclear - blows out the list, blows out the selection.
Ok, that's fine
lstCategoriesBox.Items.Add(new ListItem("--Select--", null));
lstCategoriesBox.DataTextField = "productName";
lstCategoriesBox.DataValueField = "CombinedValue";
Ok, above adds a new item. Should be ok, but one should setup the lb BEFORE adding any data - including that "--select--" row.
It just makes sense to "setup" the lb and THEN start adding data, right?
However, But, if above works - ok, then lets keep going, but I would setup the lb before adding any rows of data. Say like this:
lstCategoriesBox.DataTextField = "productName";
lstCategoriesBox.DataValueField = "CombinedValue";
lstCategoriesBox.Items.Add(new ListItem("--Select--", null));
Now, the next line:
lstCategoriesBox.SelectedValue = curCategoryProductTypeId;
Ouch! - we just cleared the lb, and now we trying to set it to a value? You can't do that - the lb just been cleared, right? You would need to load up the lb first, and THEN you can set it to the selected value, right?
I might be missing something here, but that lb needs to be loaded up with valid data BEFORE you attempt to set the selected value?
To test first, change following
Outcome Category.InnerText = list CategoriesBox.SelectedValue;
to
Category.InnerText = Request.Form["CategoriesBox-ClientID"]
If the data is coming in correctly, the list view cleared or reloaded when between reload and click events the page.
UPDATE: I just figured it out! So stupid but when I check if(selectedItem.Selected) since I'm looping through the ListBox items it starts at the first index of the ListBox and since the first isn't selected then that if goes to the else block. Remove the else and it works fine

Filtering of combobox - weird behaviour

I have a combobox in my WinForms application in which you can search for a string and results are filtered accordingly, but it seems to behave very strangely. I am searching for "Coo" and I get a very long list of products that do not contain the string "coo" (http://prntscr.com/pr54rs). However, when I type in "coor" and then press backspace, leaving me with "coo" again, the list of results is different (http://prntscr.com/pr55ef)
I am using the "KeyPress" event handler to search in the combobox. The code looks like this
private void comboBox1_KeyPress(object sender, KeyPressEventArgs e)
{
comboBox1.Items.Clear();
listNew.Clear();
var source = new AutoCompleteStringCollection();
foreach (var item in listOnit)
{
if (item.ToLower().Contains(this.comboBox1.Text.ToLower()))
{
listNew.Add(item);
}
}
comboBox1.Items.AddRange(listNew.ToArray());
comboBox1.SelectionStart = this.comboBox1.Text.Length;
Cursor = Cursors.Default;
comboBox1.DroppedDown = true;
}
Am I doing something wrong? The list is populated from a database
string sqlProducts = "SELECT Description FROM stocktake_products WHERE stocktake_id = '" + stocktakeID.stocktake_id + "' AND (PLUProdCode IS NULL OR PLUProdCode = '');";
MySqlCommand cmdProduct = new MySqlCommand(sqlProducts, conn);
cmdProduct.CommandTimeout = 10000;
MySqlDataReader rdrProduct = cmdProduct.ExecuteReader();
AutoCompleteStringCollection myCollectionSales1 = new AutoCompleteStringCollection();
if (rdrProduct.HasRows == true)
{
while (rdrProduct.Read())
{
// myCollectionSales1.Add(rdrProduct[0].ToString());
listOnit.Add(rdrProduct[0].ToString());
}
rdrProduct.Close();
//textBox1.AutoCompleteCustomSource = myCollectionSales1;
comboBox1.Items.AddRange(listOnit.ToArray());
}
I want the combobox to only display results that contain the whole string that has been typed in, not every phrase that has typed letters in any position as it seems like that's what it is doing.
I have tried to include the BeginIvoke method (not sure if done correctly thought as I have never used it before)
this.BeginInvoke((MethodInvoker)delegate
{
comboBox1.Items.Clear();
listNew.Clear();
var source = new AutoCompleteStringCollection();
foreach (var item in listOnit)
{
if (item.ToLower().Contains(this.comboBox1.Text.ToLower()))
{
listNew.Add(item);
}
}
comboBox1.Items.AddRange(listNew.ToArray());
comboBox1.SelectionStart = this.comboBox1.Text.Length;
Cursor = Cursors.Default;
comboBox1.DroppedDown = true;
});
Now when I start typing the first character, the combobox selects to top result right away (http://prntscr.com/pr5f6i). I have to press the first character again and then type the rest of the string to be able to actually search through the list.

Get return List on 3 tiers

I need return List on textbox and others controls... In my Gridview the result is ok.
I use grv.Datasouce = method... Its ok. But i dont return single values.
public Configuracoes()
{
}
public int conId { get; set; }
public string conDescricao { get; set; }
}
}
public List<Configuracoes> GetConfiguracoes()
{
List<Configuracoes> list = new List<Configuracoes>();
using (SQLiteConnection conn = new SQLiteConnection(strAppDir))
{
conn.Open();
SQLiteCommand command = new SQLiteCommand("SELECT * FROM CAP_CONFIGURACAO ORDER BY conId", conn);
SQLiteDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Configuracoes configuracoes = new Configuracoes();
configuracoes.conDescricao = reader["conDescricao"].ToString();
list.Add(configuracoes);
}
}
return list;
}
how to return this for a text box ?
txt.Text = ?
your function returns an object of type List<Configuracoes>, now you want to set it to a textbox Text property wich is a string, there is not way in this world that can be possible.
what you can do is make a string of your array and set it in the Text property of your textbox. something like
var myConfigs = GetConfiguracoes();
string myString;
foreach(var config in myConfigs){
myString += config.conDescricao;
}
txt.Text = myString;
hope it helps
Got It !
I used DataBinding on my textbox
txtPastaProcessada.DataBindings.Add(new Binding("Text", ds, "columnoftable", false, DataSourceUpdateMode.OnPropertyChanged));

Creating tooltip for multiple buttons

This code(below) suppose to add information to ToolTips which are taken from database(and the class Codons does it(it is the part that actually works)). I tried to do it in FOR loop, but it is warning me about this line:
toolTip1.SetToolTip(Convert.ToString(letter),"Name: "+fullname+" ("+cdn.GetCodon1()+")"
+"\n Begin: "+cdn.GetStart()+", End: "+cdn.GetEnd()+"");
I have 20 buttons which are named in a-z letters, except 6 specific letters(see the IF inside the FOR)
Here is the CODE:
private void UpdateToolTipButton()
{
string fullname;
Codons cdn;
char letter='a';
//get info about every amino acid from database
OleDbConnection dataConnection = new OleDbConnection();
dataConnection.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Projects_2012\\Project_Noam\\Access\\myProject.accdb";
dataConnection.Open();
for(int i=1;i<=26;i++,letter++)
{
if((letter!='b')&&(letter!='e' )&& (letter!='j') && (letter!='o')&& (letter!='u') && (letter!='z'))
{
OleDbCommand datacommand = new OleDbCommand();
datacommand.Connection = dataConnection;
datacommand.CommandText = "SELECT tblCodons.codonsFullName"
+" FROM tblCodons"
+" WHERE tblCodons.codonsCodon1="+letter;
OleDbDataReader dataReader = datacommand.ExecuteReader();
dataReader.Read();
fullname = dataReader.GetString(0);
cdn = new Codons(fullname);
toolTip1.SetToolTip(Convert.ToString(letter),"Name: "+fullname+" ("+cdn.GetCodon1()+")"
+"\n Begin: "+cdn.GetStart()+", End: "+cdn.GetEnd()+"");
}
}
}
SetToolTip is looking for a control as the first argument. You are supplying Convert.ToString(letter).
The first argument needs to be the button you want to have the tooltip:
toolTip1.SetToolTip(button1, "Name: " + fullname);
I'm guessing you were trying to set the title of the ToolTip, in which case, that's not part of the SetToolTip method. You would have to set the property yourself:
toolTip1.ToolTipTitle = Convert.ToString(letter);
If your buttons are those letters, then you would reference them by their name as the control key:
if (this.Controls.ContainsKey(Convert.ToString(letter))) {
toolTip1.SetToolTip(this.Controls[Convert.ToString(letter)], "Name: " + fullname + " etc(";
}
You shouldn't open a new reader for every item, you were also missing single quotes around an item in the where clause, but the where clause isn't necessary anyway \(^_^)_/
anyway, this is my Solution.
private char _letter;
private string _fullName;
public char Letter{
get{
return _letter;
}
set{
_letter = value;
}
}
public string FullName{
get{
return _fullName;
}
set{
_fullName = value;
}
}
Private Void UpdateToolTipButton(){
string fullname;
codons cdn;
char letter;
OleDbConnection iConnect = new OleDbConnection();
iConnect.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data
Source=#"C:\Projects_2012\Project_Noam\Access\myProject.accdb";
OleDbCommand iCommand = new OldDbCommand("Select * from tblCodons",iConnect);
List<YourClassName> iList = new List<YourClassName>();
OleDbDataReader iRead = null;
iRead = iCommand.ExecuteReader();
while(iRead.Read()){
YourClassName iClass = new YourClassName();
iClass.Letter = Convert.ToChar(iRead["codonsCodon1"]);
iClass.FullName = Convert.ToString(iRead["codonsFullName"]);
iList.Add(iClass);
}
iConnect.Close();
iRead.Close();
foreach(var VarName in iList)
{
toolTip1.SetToolTip(button1, "Name: " + var.FullName);
toolTip1.ToolTipTitle = var.Letter;
}
}
If I got it right, your Form has multiple buttons, with their Text properties set to letters a-z. the problem is that SetToolip needs the control (button) as its first parameter in order to set its tooltip, but you are passing button's text value instead.
Your loop should be arranged into something like this, so that you can iterate through actual buttons:
foreach (var button in GetButtons())
{
if (ShouldSetTooltip(button))
{
// ...
tooltip.SetTooltip(button, text);
}
}
To get all buttons placed in your form (or on a panel), you can use something like:
private IEnumerable<Button> GetButtons()
{
// this is where you decide which buttons to return
foreach (var c in this.Controls) // or panel1.Controls
if (c is Button)
yield return (Button)c;
}
And then you will probably need to add your check to skip certain button names:
private bool ShouldSetTooltip(Control c)
{
string[] lettersToSkip = new string[] { "b","e","o","u","j","z" };
return lettersToSkip.Contains(c.Text) == false;
}
[Edit]
If you want to get the control by its Name property (note: this is not the same as the Text property), you can use you loop and write it like this:
for (int i = 1; i <= 26; i++, letter++)
{
...
var button = this.Controls[letter.ToString()];
var txt = "Name: "+fullname+" ("+cdn.GetCodon1()+")"
+"\n Begin: "+cdn.GetStart()+", End: "+cdn.GetEnd()+"";
toolTip1.SetToolTip(button, txt);
}

how to set SelectedIndex in DataGridViewComboBoxColumn?

i am using a datagridview in that i am using a datagridviewcomboboxcolumn, comboboxcolumn is displaying text but the problem is i want to select the first item of comboboxcolumn by default how can i do this
DataGridViewComboBoxColumn dgvcb = (DataGridViewComboBoxColumn)grvPackingList.Columns["PackingUnits"];
Globals.G_ProductUtility G_Utility = new Globals.G_ProductUtility();
G_Utility.addUnittoComboDGV(dgvcb);
DataSet _ds = iRawMaterialsRequest.SelectBMR(bmr_ID, branch_ID, "PACKING");
grvPackingList.DataSource = _ds.Tables[0];
int i = 0;
foreach (DataRow dgvr in _ds.Tables[0].Rows)
{
grvPackingList.Rows[i].Cells["Units"].Value = dgvr["Units"].ToString();
i++;
}
The values available in the combobox can be accessed via items property
row.Cells[col.Name].Value = (row.Cells[col.Name] as DataGridViewComboBoxCell).Items[0];
the best way to set the value of a datagridViewComboBoxCell is:
DataTable dt = new DataTable();
dt.Columns.Add("Item");
dt.Columns.Add("Value");
dt.Rows.Add("Item1", "0");
dt.Rows.Add("Item1", "1");
dt.Rows.Add("Item1", "2");
dt.Rows.Add("Item1", "3");
DataGridViewComboBoxColumn cmb = new DataGridViewComboBoxColumn();
cmb.DefaultCellStyle.Font = new Font("Tahoma", 8, FontStyle.Bold);
cmb.DefaultCellStyle.ForeColor = Color.BlueViolet;
cmb.FlatStyle = FlatStyle.Flat;
cmb.Name = "ComboColumnSample";
cmb.HeaderText = "ComboColumnSample";
cmb.DisplayMember = "Item";
cmb.ValueMember = "Value";
DatagridView dvg=new DataGridView();
dvg.Columns.Add(cmb);
cmb.DataSource = dt;
for (int i = 0; i < dvg.Rows.Count; i++)
{
dvg.Rows[i].Cells["ComboColumnSample"].Value = (cmb.Items[0] as
DataRowView).Row[1].ToString();
}
It worked with me very well
If I had known about doing it in this event, it would have saved me days of digging and
trial and errors trying to get it to set to the correct index inside the CellEnter event.
Setting the index of the DataGridViewComboBox is the solution I have been looking for.....THANKS!!!
In reviewing all the issues other coders have been experiencing with trying to set
the index inside of a DataGridViewComboBoxCell and also after looking over your code,
all that anyone really needs is:
1. Establish the event method to be used for the "EditingControlShowing" event.
2. Define the method whereby it will:
a. Cast the event control to a ComboBox.
b. set the "SelectedIndex" to the value you want.
In this example I simply set it to "0", but you'd probably want to apply so real life logic here.
Here's the code I used:
private void InitEvents()
{
dgv4.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler( dgv4EditingControlShowing );
}
private void dgv4EditingControlShowing( object sender, DataGridViewEditingControlShowingEventArgs e )
{
ComboBox ocmb = e.Control as ComboBox;
if ( ocmb != null )
{
ocmb.SelectedIndex = 0;
}
}
If DataGridViewComboBoxCell already exist:
DataTable dt = new DataTable();
dt.Columns.Add("Item");
dt.Columns.Add("Value");
dt.Rows.Add("Item 1", "0");
dt.Rows.Add("Item 2", "1");
dt.Rows.Add("Item 3", "2");
dt.Rows.Add("Item 4", "3");
for (int i = 0; i < dvg.Rows.Count; i++)
{
DataGridViewComboBoxCell comboCell = (DataGridViewComboBoxCell)dvg.Rows[i].Cells[1];
comboCell.DisplayMember = "Item";
comboCell.ValueMember = "Value";
comboCell.DataSource = dt;
};
I've had some real trouble with ComboBoxes in DataGridViews and did not find an elegant way to select the first value. However, here is what I ended up with:
public static void InitDGVComboBoxColumn<T>(DataGridViewComboBoxCell cbx, List<T> dataSource, String displayMember, String valueMember)
{
cbx.DisplayMember = displayMember;
cbx.ValueMember = valueMember;
cbx.DataSource = dataSource;
if (cbx.Value == null)
{
if(dataSource.Count > 0)
{
T m = (T)cbx.Items[0];
FieldInfo fi = m.GetType().GetField(valueMember, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
cbx.Value = fi.GetValue(m);
}
}
}
It basically sets the .Display and .ValueMember properties of the DataGridViewComboBoxCell and uses a List as DataSource. It then takes the first item, and uses reflection to get the value of the member that was used as ValueMember and sets the selected value via .Value
Use it like this:
public class Customer
{
private String name;
public String Name
{
get {return this.name; }
set {this.name = value; }
}
private int id;
public int Id
{
get {return this.id; }
set {this.id = value; }
}
}
public class CustomerCbx
{
private String display;
public String Display
{
get {return this.display; }
set {this.display = value; }
}
private Customer value;
public Customer Value
{
get {return this.value; }
set {this.value = value; }
}
}
public class Form{
private void Form_OnLoad(object sender, EventArgs e)
{
//init first row in the dgv
if (this.dgv.RowCount > 0)
{
DataGridViewRow row = this.dgv.Rows[0];
DataGridViewComboBoxCell cbx = (DataGridViewComboBoxCell)row.Cells[0];
Customer c1 = new Customer(){ Name = "Max Muster", ID=1 };
Customer c2 = new Customer(){ Name = "Peter Parker", ID=2 };
List<CustomerCbx> custList = new List<CustomerCbx>()
{
new CustomerCbx{ Display = c1.Name, Value = c1},
new CustomerCbx{ Display = c2.Name, Value = c2},
}
InitDGVComboBoxColumn<CustomerCbx>(cbx, custList, "display", "value");
}
}
}
}
It seems pretty hacky to me, but I couldn't find any better way so far (that also works with complex objects other than just Strings). Hope that will save the search for some others ;)
You need to set the Items for the new cell. This must be auto done by the column when creating a new row from the UI.
var cell = new DataGridViewComboBoxCell() { Value = "SomeText" };
cell.Items.AddRange(new String[]{"SomeText", "Abcd", "123"});
something different worked for me what i did is to simply set the value of dtataGridComboBox when ever new record is added bu user with 'userAddedRow' event. For the first row I used the code in constructor.
public partial class pt_drug : PatientDatabase1_3._5.basic_templet
{
public pt_drug()
{
InitializeComponent();
dataGridView_drugsDM.Rows[0].Cells[0].Value = "Tablet";
}
private void dataGridView_drugsDM_UserAddedRow(object sender, DataGridViewRowEventArgs e)
{
dataGridView_drugsDM.Rows[dataGridView_drugsDM.RowCount - 1].Cells[0].Value = "Tablet";
}
}
Here the solution I have found : select the cell you are interested in so you can cast it to a combobox.
this.Invoke((MethodInvoker)delegate
{
this.dataGridView1.CurrentCell = dataGridView1.Rows[yourRowindex].Cells[yourColumnIndex];
this.dataGridView1.BeginEdit(true);
ComboBox comboBox = (ComboBox)this.dataGridView1.EditingControl;
comboBox.SelectedIndex += 1;
});

Categories