I have a ComboBox with several items. I have added an event handler to the SelectedIndexChanged event. Suppose, the list has two items, A and B. If the currently selected item is A and the user changes it to B then the event is fired and that's OK. However, if the user clicks on the ComboBox and clicks on A again (meaning the item has not actually changed) the event is still fired. I would like for the event to only be fired if the item has definitely changed, or something which will allow me to accomplish this.
If you don't plan change ComboBox selection diagrammatically try use SelectionChangeComitted.
Better to incapsulate this logic in class derived from ComboBox (ComboBoxEx in my example)
private class ComboBoxEx : System.Windows.Forms.ComboBox
{
Int32 _lastIndex = -1;
protected override void OnSelectedIndexChanged(System.EventArgs e)
{
if (_lastIndex == -1)
{
_lastIndex = this.SelectedIndex;
base.OnSelectedIndexChanged(e);
}
else
if (_lastIndex != this.SelectedIndex)
{
base.OnSelectedIndexChanged(e);
_lastIndex = this.SelectedIndex;
}
}
}
And use it like this:
public Form1()
{
var combobox = new ComboBoxEx() { DropDownStyle = ComboBoxStyle.DropDownList };
combobox.Items.Add("Item 1");
combobox.Items.Add("Item 2");
combobox.Items.Add("Item 3");
this.Controls.Add(combobox);
combobox.SelectedIndexChanged += OnIndexChanged;
InitializeComponent();
}
private void OnIndexChanged(object sender, EventArgs e)
{
MessageBox.Show("Index changed");
}
Simply adding the event handler to the TextChanged event instead of SelectedIndexChanged has solved my problem. This works in my case because I can be sure that no two items in the ComboBox (which is a dropdown list) will have the same text.
I think this is what you mean:
int intIndex; //Global Variable
//In your ComboBox_SelectedIndex Changed event
if(myComboBox.SelectedIndex != intIndex)
{
//your code
intIndex = myComboBox.SelectedIndex;
}
One solution would be to databind the combobox to a property in a model class. The model should then implement the interface INotifyPropertyChanged (and firing it correctly, so only when a value is changed). You can then use the PropertyChanged event to handle a change in the selection of the control, and this event would only be fired when an actual change happened.
You can define a int variable with the SelectedIndex of your ComboBox, then you can check if the variable has the same value as the index.
If yes, don't do anything, else do the stuff.
int lastIndex = myComboBox.SelectedIndex;
Then in the SelectedIndexChangedEvent:
if(lastIndex != myComboBox.SelectedIndex){
//do something
}
in your InitializeComponent(), put this in your combobox
private void InitializeComponent()
{
///combobox
///This line will triger if the combobox has changed
this.combobox.SelectedIndexChanged += System.EventHandler(this.comboboxChanged);
}
Then in your main method create the combobox method like
private string previousValue;
Private void comboboxChanged(object sender, EventArgs e)
{
if (combobox.Text == "A" && previousValue == "A")
{
//Do nothing
previousValue = "A";
}
else if (combobox.Text == "B" && previousValue == "B")
{
//Do Nothing
previousValue = "B";
}
else if (combobox.Text == "A")
{
//Do Something
previousValue = "A";
}
else if (combobox.Text == "B")
{
//Do Something
previousValue = "B";
}
}
Related
I have two ComboBoxs 1st with CmdGuarantor and the 2nd with CmdGuarantorClass as names.
CmdGuarantor has a list of 7 items:
NSSF Private MOH Army IS GS UNHCR while CmdGuranatorClass has 1st Class 2nd Class 3rd Class in its items list.
I want to disable CmdGuarantorClass whenever CmdGuarator.SelectedItem.ToString() == "Private" || CmdGuarator.SelectedItem.ToString() == "UNCHR"
how can I accomplish that?
P.S.: I tried using the EnableChanged event on CmdGuarantorClass ComboBox using this method
private void ComboBox2_EnabledChanged(object sender, EventArgs e)
{
if (CmdGuarantor.SelectedItem.ToString() == "Private" || CmdGuarantor.SelectedItem.ToString() == "UNCHR")
{
CmdGuarantorClass.Enabled = false;
}
else CmdGuarantorClass.Enabled = true;
}
but with no luck.
thank you in advance.
You should be listening for the SelectedIndexChanged event, not the EnabledChanged event. EnabledChanged is only raised when the Enabled property is changed.
Assuming the datagridview tag is a mistake and you are talking about two different winform ComboBoxes… then… I suggest you wire up the first combo boxes SelectedIndexChanged event.
This event will fire when the user changes the selection in the combo box. In that event you can check the combo box values as you have done and then set the other combo boxes Enabled property as needed. Something like…
private void comboGuarantor_SelectedIndexChanged(object sender, EventArgs e) {
if (comboGuarantor.SelectedItem.ToString() == "Private" ||
comboGuarantor.SelectedItem.ToString() == "UNCHR") {
comboGuarantorClass.SelectedIndex = -1;
comboGuarantorClass.Enabled = false;
}
else {
comboGuarantorClass.Enabled = true;
}
}
I have a problem with ListBox in c#(winforms). This ListBox contains the list of files(only pictures) in a specified directory like this:
private ListBox FileList = new ListBox();
private List<string> Directories = new List<string>
{
#"some path",
#"some other path",
#"..."
};
private List<string> Pictures;
private int selectedDirectory = 0;
public int SelectedDirectory
{
get { return selectedDirectory; }
set
{
//the list of pictures is returned correctly
Pictures = GetPictures(Directories[value]);
selectedDirectory = value;
EventHandler handler = this.DirectoryChanged;
// noone who subscribed to the event
// changes FileList.SelectedItem or FileList.SelectedIndex
if(handler != null)
handler(this, EventArgs.Empty);
this.SelectedPicture = Pictures.Count == 0 ? -1 : 0;
}
this.DirectoryChanged += (sender, e) =>
{
FileList.Items.Clear();
FileList.Items.AddRange(Pictures);
};
private int selectedPicture
public int SelectedPicture
{
get { return selectedPicture; }
set
{
selectedPicture = value;
if(value != -1)
PictureBox1.Load(Pictures[value]);
FileList.SelectedIndex = value;
}
}
// after this method returns, FileList.SelectedIndex changes to a random value depending on what Directory was selected before the change
private void MainFormKeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.NumPad5)
SelectedDirectory --;
if(e.KeyCode == Keys.NumPad2)
SelectedDirectory ++;
} // the value of SelectedIndex changes after leaving this exact line
I tried to debug it and the result was that from setting the value of FileList.SelectedIndex in this.SelectedPicture it remained 0 until MainFormKeyDown returned. EDIT: I forgot to mention that at that point FileList.SelectedIndex changes to a random value instead of 0 or -1 as it should.
What can cause this kind of behaviour and how can I solve it?
I have checked if I change the value anywhere else in the code or in any event subscription but not.
I also tried using ListView, but the result remained the same.
Now I'm out of ideas.
If the listbox has focus it could be that the KeyDown event fires the user lets go of the key and the KeyUp event fires and the list box changes its selectedIndex. Did you try changing to the KeyUp event and setting
e.Handled = true;
Handled Property
If i hold down the key KeyDown will fire a few times. You can put a Debug.WriteLine to see this if you hold down a key it will fire a few times. Another reason to use KeyUp.
I have a form that only contains an empty ComboBox.
I set the DataSource to an empty BindingList.
When I add something to the BindingList, it is selected and combobox1.SelectedIndex changes, but the event comboBox1_SelectedIndexChanged is not raised even tough it should in my opinion. Why is it not raised? When the single item is removed, the comboBox1_SelectedIndexChanged is fired correctly.
public partial class Form1 : Form
{
public Form1()
{
var test_ = new BindingList<int>();
InitializeComponent();
comboBox1.DataSource = test_;
Console.WriteLine(comboBox1.SelectedIndex); // -1
test_.Add(42); // BUG? no comboBox1_SelectedIndexChanged -> 0
Console.WriteLine(comboBox1.SelectedIndex); // 0
test_.Remove(42); // comboBox1_SelectedIndexChanged -> -1
Console.WriteLine(comboBox1.SelectedIndex); // -1
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
Console.WriteLine("index changed " + comboBox1.SelectedIndex);
}
}
You are not correct with your logic.
comboBox1.SelectedIndex is -1 doesn't mean that you have an item selected in -1 position!
It means there is no item selected in comboBox1.
Adding an item, the SelectedIndex becomes 0. No change on the selection has happened because there was no item been selected in the first place (SelectedIndex = -1).
One way to work around the bug is to tap into the ListChanged event of the BindingList collection you are using:
var test_ = new BindingList<int>();
comboBox1.DataSource = test_;
test_.ListChanged += (sender, e) => {
if (e.ListChangedType == ListChangedType.ItemAdded && test_.Count == 1) {
comboBox1_SelectedIndexChanged(comboBox1, EventArgs.Empty);
}
};
test_.Add(42);
I have this event code of the listBox:
I tried ot do it this way and it's almost working good.
private void listBox1_SelectedIndexChanged(object sender, System.EventArgs e)
{
if (recentItems.Contains(listBox1.SelectedItem))
{
itemExist = true;
item = listBox1.SelectedItem.ToString();
this.f1.PlayLightnings();
f1.pdftoolsmenu();
}
else
{
itemExist = false;
item = listBox1.SelectedItem.ToString();
recentItems.Add(listBox1.SelectedItem.ToString());
this.f1.PlayLightnings();
f1.pdftoolsmenu();
}
}
Im using a new bool variable itemExist and check and if the List recentItems wich is don't contain the selectedItem add it.
And if it does exist set the flag to true.
Then in the other code in Form1 im doing:
if (Lightnings_Extractor.Lightnings_Mode.itemExist == true)
{
if (!pdf1.Lightnings.Contains(Lightnings_Extractor.Lightnings_Mode.item))
{
pdf1.Lightnings.Add(Lightnings_Extractor.Lightnings_Mode.item);
}
}
So it's working as i wanted but the problem is that each new item i select in the listBox click on it i have to click on it twice since first time it's not in the recentItems and only on the second click it does in the recentItems and only on the second click it's changing the flag to true.
So how can i solve this problem in the SelectedIndexChanged event ?
I saw now i don't need the code part in Form1 only this code:
private void listBox1_SelectedIndexChanged(object sender, System.EventArgs e)
{
item = listBox1.SelectedItem.ToString();
this.f1.PlayLightnings();
f1.pdftoolsmenu();
if (item != null && !pdf1.Lightnings.Contains(item.ToString()))
{
pdf1.Lightnings.Add(item.ToString());
}
}
I have a Form and numericupdown control located on it. I want that in some conditions (_condition1) user cannot be able to change a value of numericupdown control. How can I do it ? I wrote some code but it works twice (double time).
class Form1 : Form
{
bool _condition1;
int _previousValue;
void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
if(_condition1)
{
numericUpDown1.Value = (decimal)_previousValue;
}
else
{
_previousValue = (int)numericUpDown1.Value;
}
}
}
Control must be enable.
numericUpDown1.ReadOnly = true;
?
.... edit: ..........
Another (ugly) solution would be to remove the event, change the value, and add the event again ..
numericupdown1.ValueChanged -= new EventHandler ....
numericupdown1.Value = value;
numericupdown1.ValueChanged += new EventHandler ....
Have you tried using the Validating event?
EDIT #1 Have you tried the Leave event?