ComboBox Index Changed - c#

Need to know: I am working with Windows Forms in Visual Studio and C#.
I have 5 comobobox's that I populate from SQL with the parts available in the DB. Part of the coding to it, one uses a DataTable and set the DataSource of the comboBox to that DataTable.
In this same DataTable via my SQL query, I have listed the cost of the part in the list. What I want to do is whichever part you pick from the dropdown list, the related price must show in the textbox next to it.
I am trying to use the comboBox1_SelectedIndexChanged for this, but the problem I run into is as soon as the DataSource gets set to the DataTable while the form's initial loading, it gets picked up as a Index change and the comboBox1_SelectedIndexChanged wants to run. But at this point in time, the SelectedIndex Value is null due to it still loading, causing it to give me a exception cast error.
how can I work around this?
DataTable SparePart = new DataTable() is declared outside the function to make it available as "public" so that the comboBox1_SelectedIndexChanged can access it.
Then I have this code to populate the comboBox:
//Read Status info from DB
SqlDataAdapter SparePartReader = new SqlDataAdapter(SQLSparePartDropbox);
SparePartReader.Fill(SparePart);
comboBoxFinJCSpares1.DataSource = SparePart;
comboBoxFinJCSpares1.DisplayMember = "DisplayMember";
comboBoxFinJCSpares1.ValueMember = "PartID";
//Set Combox1 affiliated Cost value to cost textbox
int ComBo1PartID = (int)comboBoxFinJCSpares1.SelectedValue;
string CostPrice = (from DataRow dr in SparePart.Rows
where (int)dr["PartID"] == ComBo1PartID
select (string)dr["PartCost"]).FirstOrDefault();
textBoxFinJCCost1.Text = CostPrice.ToString();
and then I have this for the comboBoxFinJCSpares1_SelectedIndexChanged:
//Set Combox1 affiliated Cost value to cost textbox
int ComBo1PartID = (int)comboBoxFinJCSpares1.SelectedValue;
string CostPrice = (from DataRow dr in SparePart.Rows
where (int)dr["PartID"] == ComBo1PartID
select (string)dr["PartCost"]).FirstOrDefault();
textBoxFinJCCost1.Text = CostPrice.ToString();
enter image description here

The solution is as easy as making one boolean variable and call it formLoaded.
Set it to false, then set it to true after the form loads.
Put your code for populating combobox inside if statement and that should do it
Cheers ~ ChenChi
demo:
//Read Status info from DB
if(formLoaded)
{
SqlDataAdapter SparePartReader = new SqlDataAdapter(SQLSparePartDropbox);
SparePartReader.Fill(SparePart);
comboBoxFinJCSpares1.DataSource = SparePart;
comboBoxFinJCSpares1.DisplayMember = "DisplayMember";
comboBoxFinJCSpares1.ValueMember = "PartID";
//Set Combox1 affiliated Cost value to cost textbox
int ComBo1PartID = (int)comboBoxFinJCSpares1.SelectedValue;
string CostPrice = (from DataRow dr in SparePart.Rows
where (int)dr["PartID"] == ComBo1PartID
select (string)dr["PartCost"]).FirstOrDefault();
textBoxFinJCCost1.Text = CostPrice.ToString();
}

Thanks guys, the "SelectedChangeCommitted" option suggested by Marcel Hoekstra solved my problem.

Related

Problem with format in C# with DataGridView and TextBox

I have a problem with format in C#.
I have a DataGridView and a TextBox. In this datagridview, there is a column: the single price (format int).
I want sum every elements of single price's column and insert the result into this textbox, but Visual Studio gives me a problem with format of string input ("Format of input's string is not correct").
this is the code than i used:
int TOT = 0;
for (int i = 0; i < dataGridView3.Rows.Count; i++)
{
TOT = TOT + Convert.ToInt32(dataGridView3.Rows[i].Cells[6].ToString());
}
textBoxTot.Text = Convert.ToString(TOT);
Can you help me with this bad error?
UPDATE:
I think that the problem now is another. I can't find the methods of MySql.Data.MySqlClient library that it can give me the result of query.
MySqlCommand command = new MySqlCommand();
String sumQuery = "SELECT SUM(`prezzo`) FROM `fatturetemp`";
command.CommandText = sumQuery;
command.Connection = conn.getConnection();
command.Parameters.Add("#prezzo", MySqlDbType.Int32).Value = costo;
conn.openConnection();
conn.closeConnection();
How is the command that give me the result of sumQuery. If i find this command, i can take the result of query and paste in textbox
If your datagridview is showing a datatable (I.e. your data is stored in a datatable) you can add a DataColumn to the datatable whose .Expression property is set to the string "SUM([Price])", where Price is the name of your numeric datatyped column holding the price info.
Now every row in the table will have the sum of the prices (the same value over and over again), so if you want to databind your textBox to this new column then it will always show the sum no matter which row is the current row (because all rows have the same value). It will also auto update without you having to do anything!
And if you're not using databinding to a datatable, I recommend that you do do it, because it represents good MVC practice of keeping your data in one thing (DataTable) and showing it in another (DataGridView) and keeping these concerns separate
It would look something like this, as a quick example:
DataTable dt = new DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("Price", typeof(int));
dt.Columns.Add("CalculatedTotal", typeof(int)).Expression = "SUM([Price])";
dt.Rows.Add("Apples", 100);
dt.Rows.Add("Oranges", 200);
BindingSource bs = new BindingSource();
bs.DataSource = dt;
WhateverDataGridView.DataSource = bs;
totalTextBox.DataBindings.Add(new Binding("Text", bs, "CalculatedTotal", true));
Here we have a data model (the datatable) where we keep our data. It has a couple of things we can set directly, and an third column that calculates based on the existing prices in all the table. If you look at this in the datagridview (assuming you have autogeneratecolumns turned on) you'll see that both rows have 300 for the CalculatedTotal, but they have individual amounts for price. There is a device called a BindingSource that sits between the datatable and the UI controls; you don't have to have one but it makes certain things easier regards updating controls when the data changes, and it maintains a concept of "current" - essentially whatever the current row is you're looking at in the datagridview; it all helps to avoid having to ask the DGV for anything - we just let the user type into the DGV, and it shows the data out of the datatable. All our dealings can be with the datatable directly - if you wrote a button to loop through the table and double all the prices, the controls in the UI would just reflect the change automatically. The textbox is connected to the CalculatedValue column via databinding; whatever the current row is, the textbox will show the CalculatedValue. Because the CalculatedValue column has the same value on every row, and they always all update if any price changes, the total textbox will always show the total. Add another textbox bound to Name to see what I mean; as you click around the grid and select different rows to be the "Current" row, the Name will change but the total does not. In truth it is actually changing in the same way that Name is, it's just that because the actual numeric value is the same on every row the contents of the textbox look like they don't change
UPDATE: I think that the problem now is another. I can't find the methods of MySql.Data.MySqlClient library that it can give me the result of query.
public string sommaFattura(String costo)
{
MySqlCommand command = new MySqlCommand();
String sumQuery = "SELECT SUM(`prezzo`) FROM `fatturetemp`";
command.CommandText = sumQuery;
command.Connection = conn.getConnection();
command.Parameters.Add("#prezzo", MySqlDbType.Int32).Value = costo;
conn.openConnection();
conn.closeConnection();
}
How is the command that give me the result of sumQuery. If i find this command, i can take the result of query and paste in textbox
It is weird that you are first converting to a string and then to an int.
int TOT = 0;
for (int i = 0; i < dataGridView3.Rows.Count; i++)
{
if (!dataGridView3.Rows[i].IsNewRow &&
int.TryParse(dataGridView3.Rows[i].Cells[6].Value.ToString(), out int v))
TOT += v;
}
textBoxTot.Text = TOT.ToString();
EDIT: Edited for your updated question. You shouldn't ask question inside a question buy anyway:
string sumQuery = "SELECT SUM(`prezzo`) FROM `fatturetemp`";
decimal total = 0M;
using (MySqlConnection cn = new MySqlConnection(" your connection string here "))
using (MySqlCommand cmd = new MySqlCommand(sumQuery, cn))
{
cn.Open();
total = Convert.ToDecimal(cmd.ExecuteScalar());
cn.Close();
}
Console.WriteLine(total);

Drop Down List is not finding correct value

When I connect my dropdownlist (cmbStaff) and then try and apply a selected value to cmbStaff it will always return the very first value within the dropdownlist.
Here is the code I use to bind data to the dropdownlist
if(!IsPostBack)
{
String Sql = #" select * from SupportTeam";
SqlConnection conn = new SqlConnection(Properties.Resources.cString);
SqlDataAdapter DA = new SqlDataAdapter(Sql, Properties.Resources.cString);
DataSet DS = new DataSet();
DA.Fill(DS, "SupportTeam");
cmbStaff.DataValueField = "SupportTeamID";
cmbStaff.DataTextField = "SupportTeamName";
cmbStaff.DataSource = DS;
cmbStaff.DataBind();
cmbStaff.Items.Insert(0, "--Please select a support team--");
}
But in future code when I try and apply a selected value to the drop down it will always select the first index.
For example, if I do this
cmbStaff.SelectedValue = "TEL";
When I debug, it will always return this
cmbStaff.SelectedValue = "--Please select a support team--"
cmbStaff.SelectedIndex = 0;
Why is it doing this.
I have data stored in the table as the combo works it just does not set starting index to the value that I want and that is what I need it to do.
Here is a snippet of the data I have stored in the SupportTeam Table
Sorry if is seem vague, thanks in advance!
That is not how you set a selected value for a drop down list. you use the findbyvalue function and set selected =true
cmbStaff.Items.FindByValue("TEL").Selected = true;
The problem I was having was Sql Related. It keep adding blank spaces onto the end of the value I was entering. I changed
String Sql = #" select * from SupportTeam";
to
String Sql = #" select rtrim(SupportTeamID) as SupportTeamID, rtrim(SupportTeamName) as SupportTeamName from SupportTeam";
It now works. I cannot find the exact reason why this happened. Of course the .Trim() function will also work when declaring Sql variables in c#.

DataGridView bound with binding list displays blank rows

I have table in my database stored in SQL Server 2012 and through this table I am iterating and adding new object in my binding list. This list is then set as datasource for my DataGridView.
As I understand, the DataGridView should create columns and fill the rows with data, but when I run the build, I only see blank rows. Their count is matching the count of rows in table and I also debugged with breakpoints so I have determined that I really have my datasource filled with data, but I cannot figure those blank rows out.
This is method I use for creating dataset and filling the binding list
public void selectCars()
{
string connString = #"Data Source=POHJOLA\SQLEXPRESS;Initial Catalog=BlueCars;Integrated Security=True";
using (SqlConnection connection = new SqlConnection(connString))
{
connection.Open();
string query = "SELECT * FROM Car ORDER BY CarID ASC";
SqlCommand command = new SqlCommand(query, connection);
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
using (DataSet result = new DataSet())
{
adapter.Fill(result);
foreach (DataRow row in result.Tables[0].Rows)
{
carsList.Add(new Car(Convert.ToInt32(row[0]), row[1].ToString(), row[2].ToString(), row[3].ToString(), Convert.ToDecimal(row[4]),Convert.ToInt32(row[5]),row[6].ToString(),row[7].ToString() ));
}
}
}
}
This is my initialization
public managerCarForm()
{
InitializeComponent();
selectCars();
carsGrid.DataSource = carsList;
}
Also I should probably add, that I created columns manually in designer and set datanameproperty to parameters of the car class
I am not getting any exception or error here..
Thanks very much in advance!
I came across the exact same problem in VB.
I Found out that the solution was this:
(I´ll just write my code in VB you can translate it).
Before setting the DataSource of the grid, you should Clear the grid out.
carsGrid.DataSource = Nothing
carsGrid.Rows.Clear()
carsGrid.Columns.Clear()
Then set your grid DataSource as usual. In My case:
carsGrid.DataSource = GetEmptyObject._Get()
Hope it Helps.
foreach (DataRow row in result.Tables[0].Rows)
{
carsList.Add(new Car(Convert.ToInt32(row[0]), row[1].ToString(), row[2].ToString(), row[3].ToString(), Convert.ToDecimal(row[4]),Convert.ToInt32(row[5]),row[6].ToString(),row[7].ToString() ));
}
Please check your carList by applying a breakpoint after foreach loop to verify it contains at least a single data row. And also check your query.
If your application is an ASP.NET
try to modify your code as below..
public managerCarForm()
{
InitializeComponent();
selectCars();
carsGrid.DataSource = carsList;
carsGrid.Databind();
}
Normally this happens when you have manually added the columns in design time.
Or you have AutoGenerateColumns = false;
If you use AutoGenerateColumns = true; the columns will be/should be auto generated.
To solve this:
Right click on the grid -> Edit Columns.
Go to property: DataPropertyName
Set that to the variable name that you bind to (the table column name in your case).
(You say you have done that, but the value here should exactly match what you have in your list. I have made a DTO class and via a loop I have populated a List of my own and set the names to match the properties of that DTO. This should solve it for you.)

Populating a dropdownlist with a specific value plus an array of values from an sql query

I am new to the wonderful world of dropdownlists and I know this is going to be difficult for me to explain but I will try the best I can.
Here is my data:
**Type** **ID** **Status**
Letter 1 A
Letter 2 B
Letter 3 C
Letter 4 D
Letter 5 E
From my query result I return the ID of "3" and my Drop Down List displays a "C". I have accomplished this piece already :). My question is, how can I populate the dropdownlist with the Statuses? My DDL will display a "C" and when it the arrow is clicked, the rest of the Status values will be displayed.
Is this something that can be done with the sql query? Do I have to create a separate method? If someone could point me in the right direction or provide some helpful code that would be awesome! Here is my code:
SqlDataAdapter adapter = new SqlDataAdapter("SELECT Status FROM dbo.database WHERE ID = #ID AND Type = 'Letter'", mySqlConnection1);
adapter.SelectCommand.Parameters.Add("#ID", SqlDbType.Char).Value = lblID.Text;
adapter.Fill(test);
ddlStatus.DataSource = test;
ddlStatus.DataTextField = "Status";
ddlStatus.DataValueField = Status";
ddlStatus.DataBind();
I think this is what you are looking for:
SqlDataAdapter adapter = new SqlDataAdapter(
"SELECT ID, Status FROM dbo.database WHERE Type = 'Letter'",
mySqlConnection1);
adapter.Fill(test);
ddlStatus.DataSource = test;
ddlStatus.DataTextField = "Status";
ddlStatus.DataValueField = "ID";
ddlStatus.DataBind();
ddlStatus.SelectedValue = lblID.Text;
First, fill the DropDownList with the values you need, then set the SelectedValue to have that value automatically displayed. From what I understand, you want the Status to be displayed to the user, but the actual selected value should be the ID.
Depending on your usage of ViewState, you may only need to load the DropDownList once (when the page is first loaded) and then simply set the SelectedValue after that. (You'd need to reload the list on a second page load. Use the IsPostBack value to determine whether or not to reload). There is, however, very little harm in reloading each time, other than a fraction of a second being added to your page load time.
I think what you are looking for is SelectedValue
ddlStatus.DataSource = test;
ddlStatus.DataTextField = "Status";
ddlStatus.DataValueField = "ID";
ddlStatus.DataBind();
//Add this line
string defaultValue = "3";
ddlStatus.SelectedValue = defaultValue; //C has ID of 3

TextBox AutoComplete from MDB

I have a .Net 4 Windows Forms app that uses a Microsoft Access Database with one table which has three columns CityCode, Name and Country.
What I want to do is have an autocomplete which shows the “Name” and “Country” but when selected the “CityCode” Value is shown in the textbox. In addition if the user types A City Code eg LAX as they type L it would list all the cities whose code or Name starts with L.
Can this be done?
Currently I have the following for access the database (but it seems to be a bit slow!)
textBoxCity.AutoCompleteCustomSource = CityList();
public static AutoCompleteStringCollection CityList()
{
string connectionStringLD = string.Empty;
connectionStringLD = #"Driver={Microsoft Access Driver (*.mdb)};DBQ=c:\CityList.mdb";
string SQL = "SELECT CityCode from CityTable";
OdbcConnection conn = new OdbcConnection(connectionStringLD);
OdbcCommand cmd = new OdbcCommand(SQL);
cmd.Connection = conn;
conn.Open();
OdbcDataReader reader = cmd.ExecuteReader();
AutoCompleteStringCollection theCityList = new AutoCompleteStringCollection();
while (reader.Read())
{
theCityList.Add(reader.GetValue(0).ToString());
}
return theCityList;
}
You can use Like '%' Query in your Sql Statement which will return the city name based on your input.
You can Refer this example Sql Parameter with C# Using Like wildCards
I'm not sure what you're getting at with
What I want to do is have an autocomplete which shows the “Name” and “Country” but when selected the “CityCode” Value is shown in the textbox.
but I can answer the autocomplete part of your question.
To do this you need to get your data into a DataTable; you can read it from the database into the table however you want, but the Right Way to do it is to use OleDbConnection, OleDbDataAdapter, and OleDbCommandBuilder - msdn has examples.
Now that it's in a DataTable, bind it to a ComboBox:
var query =
from row in mytable.AsEnumerable()
select new { citycode = row.Field<string>("CityCode") } // put whatever you want in the anonymous type
mycombobox.DisplayMember = "citycode"
mycombobox.ValueMember = "citycode" // this one can be a different member name
mycombobox.DataSource = query.toList(); // the datasource should be set last
And now you can set the combo box behavior to be an autocomplete:
combobox1.AutoCompleteMode can be set to Append (to simply autocomplete), Suggest (to bring up a dropdown box), or SuggestAppend (both)
Set combobox1.AutoCompleteSource to ListItems to have it get the autocomplete entries from the data binding.
If you prefer to allow users to type whatever they want and only suggest your datatable values as options, then you should only set the AutoCompleteCustomSource and not worry about actual data binding with DataSource.
This is kind of all a lot of trouble; since cities aren't exactly going to be opening international airports several times a second you might prefer just dumping all the airport codes into a List, which you can also data bind to.

Categories