Why am I getting Stale Data in my databound ComboBox? - c#

I have a form with 2 databound listboxes and two databound comboboxes. I'm using typed datasets. The controls are bound to a pair of tables with the following schema and data from this schema. One listbox and one comboBox are bound to the bar table; the other listbox and comboBox are bound to the foo table.
When the SelectedIndexChanged Event fires for the foo listBox I get the current value for the Selected Text in the Bar listBox and comboBox.
However, when I use the foo comboBox and try to access the barComboBox.SelectedText inside the FooComboBox_SelectedIndexChanged event I get the previously selected value from SelectedText instead of the new value. The BarListBox.Selected gives me the current value.
Note that I use the FooListBox to do the selection, both event handlers function as expected.
Can anyone explain what's going on here and how to work around this?
Form Screenshot w/sample data:
The dataset designer:
The form1.cs code:
//Standard using statements and namespace info
public partial class Form1 : Form
{
//Loading DataSets and initializing here
private void FooListBox_SelectedIndexChanged(object sender, EventArgs e)
{
Console.WriteLine("The value in the bar ListBox is {0}", barListBox.Text);
}
private void FooComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
Console.WriteLine("The value in the bar comboBox is {0}", barComboBox.Text);
}
}

I didn't find any behaviour as you Explained.
pleas check this code , Please do correct me reproduced code is wrong.
I have used Combo Box items and ListBox items are added in FormLoad as DataSource from Some webServiceMethod
in Form1.Designer.cs
this.comboBox1 = new System.Windows.Forms.ComboBox();
this.listBox1 = new System.Windows.Forms.ListBox();
this.SuspendLayout();
//
// comboBox1
//
this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBox1.FormattingEnabled = true;
this.comboBox1.Location = new System.Drawing.Point(32, 55);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(188, 21);
this.comboBox1.TabIndex = 0;
this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
//
// listBox1
//
this.listBox1.FormattingEnabled = true;
this.listBox1.Location = new System.Drawing.Point(261, 55);
this.listBox1.Name = "listBox1";
this.listBox1.Size = new System.Drawing.Size(255, 95);
this.listBox1.TabIndex = 1;
this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged);
*in Form1.cs*
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
MessageBox.Show("The value in the bar comboBox is "+ comboBox1.Text);
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
MessageBox.Show("The value in the bar comboBox is "+ listBox1.Text);
}
private void Form1_Load(object sender, EventArgs e)
{
WebServiceRef.CM_ServiceSoapClient soapClient = new WebServiceRef.CM_ServiceSoapClient();
comboBox1.DataSource = soapClient.GetAllCategories();
listBox1.DataSource = soapClient.GetAllCategories();
}
I have changed the Data According to DataSource form WebService Method, Still I didn't find any issues as you exaplined your beahaviour.

Related

Change visible state of DataGridView only given its name

I have a form application where multiple DataGridView objects are to be displayed (but not at once). They should be created on top of each other and it should then be possible to toggle the displayed DataGridView using a ComboBox.
I have a function which should create new DataGridView every time its called and then adds the name to the ComboBox:
private void readCSV(string DBname)
{
DataGridView tagDBname = new DataGridView();
tagDBname.Location = new System.Drawing.Point(24, 260);
tagDBname.Name = DBname;
tagDBname.Size = new System.Drawing.Size(551, 217);
tagDBname.TabIndex = 6;
tagDBname.Columns.Add("Column1", "Col1");
tagDBname.Columns.Add("Column2", "Col2");
tagDBname.Visible = false;
comboBoxTag.Items.Add(DBname);
}
Then I would like to change the visibility state of a DataGridView given the selected name from the ComboBox. This should be done in the function called when the index changes:
private void comboBoxTag_SelectedIndexChanged(object sender, EventArgs e)
{
// Get the name of the DataGridView which should be visible:
string selectedTagDB = comboBoxTagDatabases.SelectedItem.ToString();
DataGridView tagDatabase = ? // Here the DataGridView should be selected given the name "selectedTagDB"
tagDatabase.Visible = true;
}
In the above, I do not know how to assign the DataGridView only given its name. Any help would be appreciated - even if it means that the selected approach is inappropriate of what I am trying to achieve. If the question is answered elsewhere, feel free to guide me in the right direction :)
I would store the gridviews in a dictionary by using the DB name as key;
private readonly Dictionary<string, DataGridView> _tagDBs =
new Dictionary<string, DataGridView>();
private void readCSV(string DBname)
{
DataGridView tagDBname = new DataGridView();
// Add the gridview to the dictionary.
_tagDBs.Add(DBname, tagDBname);
tagDBname.Name = DBname;
tagDBname.Location = new System.Drawing.Point(24, 260);
tagDBname.Size = new System.Drawing.Size(551, 217);
tagDBname.TabIndex = 6;
tagDBname.Columns.Add("Column1", "Col1");
tagDBname.Columns.Add("Column2", "Col2");
tagDBname.Visible = false;
this.Controls.Add(tagDBname); // Add the gridview to the form ot to a control.
comboBoxTag.Items.Add(DBname);
}
private void comboBoxTag_SelectedIndexChanged(object sender, EventArgs e)
{
// Get the name of the DataGridView which should be visible:
string selectedTagDB = comboBoxTagDatabases.SelectedItem.ToString();
foreach (DataGridView dgv in _tagDBs.Values) {
dgv.Visible = dgv.Name == selectedTagDB; // Hide all gridviews except the selected one.
}
}
If you need to do something with the selected gridview, you can get it with:
if (_tagDBs.TryGetValue(selectedTagDB, out DataGridView tagDatabase)) {
// do something with tagDatabase.
}
Note: you must add the gridview to the form or to a container control on the form. E.g.
this.Controls.Add(tagDBname);
You can loop through all DataGridViews of the form to display the expected one using its name, while hidding the others ones.
This solution isn't pretty but works
private void ShowOneDataGridViewAndHideOthers(string name)
{
foreach (var DGV in this.Controls.OfType<DataGridView>())
{
DGV.Visible = DGV.Name == name;
}
}
And call it this way :
private void comboBoxTag_SelectedIndexChanged(object sender, EventArgs e)
{
// Get the name of the DataGridView which should be visible:
string selectedTagDB = comboBoxTagDatabases.SelectedItem.ToString();
ShowOneDataGridViewAndHideOthers(selectedTagDB);
}
The method can be made a bit more generic this way :
private void ShowOneControlAndHideOthers<T>(string name, Control controls) where T : Control
{
foreach (var control in controls.Controls.OfType<T>())
{
control.Visible = control.Name == name;
}
}
private void comboBoxTag_SelectedIndexChanged(object sender, EventArgs e)
{
// Get the name of the DataGridView which should be visible:
string selectedTagDB = comboBoxTagDatabases.SelectedItem.ToString();
ShowOneControlAndHideOthers<DataGridView>(selectedTagDB, this);
}

Event immediatelly as another item is selected in DataGridViewComboBoxCell

I initialize cells from a list like this:
DataGridViewRow row = new DataGridViewRow();
List<string> itemNames = new List<string>(new string[]
{
"ITEM 1",
"ITEM 2",
"ITEM 3",
"Add new item..."
});
row.CreateCells(myDataGridView);
row.Cells[0].Value = "";
if(row.Cells[1] is DataGridViewComboBoxCell cell2)
{
cell2.DataSource = itemNames;
}
In the real program, the list is loaded from somewhere and the "Add new item..." entry is added at the end. What I want is to show a form when "Add new item..." is selected in the combobox.
protected void checkIfNewItemSelected(DataGridViewComboBoxCell combocell)
{
if (combocell.Value + "" == ADD_CONFIG_TEXT)
{
// do something to add new item (show a form)
}
}
However I cannot find any suitable event that would trigger immediatelly after user selects the value. For example I tried CellEndEdit and CurrentCellDirtyStateChanged on the datagrid. Both of these events trigger only after the combobox loses focus. Specifically the latter is recommended by MSDN:
private void dataGridViewConfigs_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
DataGridViewCell cell = dataGridViewConfigs.CurrentCell;
// handle trigger for new PRJ config request
if (cell is DataGridViewComboBoxCell combocell)
{
checkIfNewItemSelected(combocell);
}
}
So if you select the "Add new item...", this is what you end up seeing:
Only after you click somewhere else, the events that I tried are triggered. I need to take action IMMEDIATELY after user clicks on this particular entry.
How to do that?
You could hook up to the events directly on the editing control, for example...
private const string NEW_ITEM_TEXT = "Add new item..";
private void Form1_Load(object sender, EventArgs e)
{
var comboCol = new DataGridViewComboBoxColumn();
comboCol.Items.AddRange("A", "B", NEW_ITEM_TEXT);
dataGridView1.Columns.Add(comboCol);
dataGridView1.EditingControlShowing += DataGridView1_EditingControlShowing;
}
private void DataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
var comboBox = e.Control as ComboBox;
if (comboBox == null) return;
comboBox.SelectedIndexChanged -= ComboBox_SelectedIndexChanged;
comboBox.SelectedIndexChanged += ComboBox_SelectedIndexChanged;
}
private void ComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
DataGridViewComboBoxEditingControl editor = sender as DataGridViewComboBoxEditingControl;
if (editor.SelectedItem.ToString() != NEW_ITEM_TEXT) return;
Form2 f2 = new Form2();
f2.Show();
}

How to update datagridview based off of combo box selection?

I am attempting to write code that will display data in a datagridview based off of the size of car selected in a combo box. When this code initially runs, it defaults to economy sized, and displays the correct information in the datagridview. However, when a different size is selected in the combo box, the text boxes update correctly while the datagridview remains the same. What can I do to make it update every time the combo box is changed? I thought the code in "private void cboSize_selectionChangeCommitted()" would accomplish this, but there was no change in the output.
namespace carForm
{
public partial class Form1 : Form
{
_Cars_1_DataSet cDataSet;
BindingSource sizeBindingSource;
BindingSource vehicleBindingSource;
CarsDataClass clsCarsData;
Boolean gridInitialized;
public Form1()
{
InitializeComponent();
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Close();
}
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the '_Cars_1_DataSet.Reservations' table. You can move, or remove it, as needed.
this.reservationsTableAdapter.Fill(this._Cars_1_DataSet.Reservations);
// TODO: This line of code loads data into the '_Cars_1_DataSet.Vehicle' table. You can move, or remove it, as needed.
this.vehicleTableAdapter.Fill(this._Cars_1_DataSet.Vehicle);
// TODO: This line of code loads data into the '_Cars_1_DataSet.CarSize' table. You can move, or remove it, as needed.
this.carSizeTableAdapter.Fill(this._Cars_1_DataSet.CarSize);
clsCarsData = new CarsDataClass();
cDataSet = clsCarsData.GetDataSet();
//Binding source sizes
sizeBindingSource = new BindingSource();
sizeBindingSource.DataSource = cDataSet;
sizeBindingSource.DataMember = "CarSize";
//Binding source vehicles
vehicleBindingSource = new BindingSource();
vehicleBindingSource.DataSource = cDataSet;
vehicleBindingSource.DataMember = "Vehicle";
//Combo box
cboSize.DataSource = sizeBindingSource;
cboSize.DisplayMember = "Size";
cboSize.ValueMember = "SizeCode";
//bind other controls
txtDaily.DataBindings.Add("text", sizeBindingSource, "DailyRate");
txtMileage.DataBindings.Add("text", sizeBindingSource, "MileageRate");
//execute combo box
cboSize_SelectionChangeCommitted(cboSize, e);
}
private void cboSize_SelectionChangeCommitted(object sender, EventArgs e)
{
string carSelected;
carSelected = Convert.ToString(cboSize.SelectedValue);
if (!gridInitialized)
{
dgvVehicles.DataSource = vehicleBindingSource;
gridInitialized = true;
ChangeGridColumns();
}
vehicleBindingSource.Filter = "CarSize = '" + carSelected + "'";
}
private void ChangeGridColumns()
{
//Change column headers
//dgvVehicles.Columns["Inv_ID"].Visible = false;
}
}
}
Try using SelectedIndexChanged event from the events menu after clicking on the combobox in the design view.
This should populate in your code:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
Console.WriteLine("test!");
}
In there you can put this logic from your code:
string carSelected;
carSelected = Convert.ToString(cboSize.SelectedValue);
if (!gridInitialized)
{
dgvVehicles.DataSource = vehicleBindingSource;
gridInitialized = true;
ChangeGridColumns();
}
vehicleBindingSource.Filter = "CarSize = '" + carSelected + "'";
Use SelectedIndexChanged instead of SelectionChangeCommitted.

Retrieving value from combo box selected item

I am using Windows Application.I Put some data as direct values in combo box.I defined var type to combo box.I put these combo box on form load.Now I want to retrieve the value of selected item on my button2_click event and I tried below code to retrieve it,but it giving me error of The name comboBox does not exist in current context.Can any one suggest me how to fix it.
namespace WinDataStore
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var daysOfWeek =
new[] { "RED", "GREEN", "BLUE"
};
// Initialize combo box
var comboBox = new ComboBox
{
DataSource = daysOfWeek,
Location = new System.Drawing.Point(180, 140),
Name = "comboBox",
Size = new System.Drawing.Size(166, 21),
DropDownStyle = ComboBoxStyle.DropDownList
};
// Add the combo box to the form.
this.Controls.Add(comboBox);
}
private void button1_Click(object sender, EventArgs e)
{
// Create a new instance of FolderBrowserDialog.
FolderBrowserDialog folderBrowserDlg = new FolderBrowserDialog();
// A new folder button will display in FolderBrowserDialog.
folderBrowserDlg.ShowNewFolderButton = true;
//Show FolderBrowserDialog
DialogResult dlgResult = folderBrowserDlg.ShowDialog();
if (dlgResult.Equals(DialogResult.OK))
{
//Show selected folder path in textbox1.
textBox1.Text = folderBrowserDlg.SelectedPath;
//Browsing start from root folder.
Environment.SpecialFolder rootFolder = folderBrowserDlg.RootFolder;
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
if (!textBox1.Text.Equals(String.Empty))
{
if (System.IO.Directory.GetFiles(textBox1.Text).Length > 0)
{
foreach (string file in System.IO.Directory.GetFiles(textBox1.Text))
{
//Add file in ListBox.
listBox1.Items.Add(file);
}
}
else
{
// listBox1.Items.Add(String.Format(“No files Found at location:{0}”, textBox1.Text));
}
}
string s = (string)comboBox.SelectedItem;
listBox1.Items.Add(s);
}
}
}
comboBox was local variable in Form1 .ctor. You can't access it from another method
options:
1) access to the control by name
private void button2_Click(object sender, EventArgs e)
{
var comboBox = this.Controls["comboBox"] as ComboBox;
...
}
2) make it a private member of the form as controls normally are, if they are created in designer
ComboBox comboBox;
public Form1()
{
InitializeComponent();
// Initialize combo box
comboBox = new ComboBox() {...};
...
}
Currently the Combobox appears to be a local variable. Try to make it a global field variable and you should be able to access it.

Listview as a log file

Hi. I have a Windows form application. After I do something, what I want is to put updates in the Listview. More like a log file. Here is my code:
private void Form1_Load(object sender, EventArgs e)
{
listView1.View = View.Details;
listView1.GridLines = true;
listView1.FullRowSelect = true;
//Add column header
listView1.Columns.Add("Import Status", 100);
listView1.Columns.Add("Price", 70);
listView1.Columns.Add("Date", 70);
//Add items in the listview
string[] arr = new string[4];
ListViewItem itm;
//Add first item
arr[0] = "product_1";
arr[1] = "100";
arr[2] = "10";
itm = new ListViewItem(arr);
listView1.Items.Add(itm);
//Add second item
arr[0] = "product_2";
arr[1] = "200";
arr[2] = "20";
itm = new ListViewItem(arr);
listView1.Items.Add(itm);
}
How can I Add items to the ListView without 'hardcoding' them? Any suggestions? How can I do that every Button.Click, it can add rows with some data in it?
How can I Add items to the ListView without 'hardcoding' them?
Code
private void Form1_Load(object sender, EventArgs e)
{
listView1.View = View.Details;
listView1.GridLines = true;
listView1.FullRowSelect = true;
listView1.Columns.Add("Import Status");
listView1.Columns.Add("Price");
listView1.Columns.Add("Date");
}
private void btnAdd_Click(object sender, EventArgs e)
{
ListViewItem LVI = new ListViewItem(txtstatus.Text);
LVI.SubItems.Add(txtPrice.Text);
LVI.SubItems.Add(txtDate.Text);
listView1.Items.Add(LVI);
}
UI
Globalize your these two lines to allow your access in every method of your class:
string[] arr = new string[4];
ListViewItem itm;
Now create a button click event and put your code in it:
private void button1_Click(object sender, EventArgs e)
{
arr[0] = "product_2"; //you can get these values from textboxes if you are taking input from user
arr[1] = "200";
arr[2] = "20";
itm = new ListViewItem(arr);
listView1.Items.Add(itm);
}
hi there :) you could use a datagridview instead of the listview control.
all you have to do is to define an own dataset or add a dataset control
to your project. u just need to add your three columns to a new datatable in there.
then:
add that dataset to your form, it will appear in your form code
set the datasource of the datagridview to the added dataset
now you can add new datarows to the datatable and they will appear in the datagridview automatically. the good thing is, you have to define your table layout once and the designer will generate you a custom datarow type, what you can use.
my experience told me, that this way is more comfortable than using listview. the main thing is, u can LINQ over the datatable if you want to process data from there in other
context. i used listview before, but since datagridview in combination with dataset, everything is better ;)
sincerly,
ceth

Categories