I have a Listbox that allows you to select different menus. Say my Listbox contains 3 indexes. 1, 2, and 3. Index 3 is special and does things that effect 1 and 2. I want to do a specific action if the selected index changes from 3 to any other index.
Basically I want the following.
if (selectedindex was = 3)
{
//Do stuff
}
Edit: I wanted to clarify a little bit. My listbox contains 3 things you can select, see below. Bare in mind that the numbers are used for my example.
So, if I click on 3, then click on 1 or 2, I want it to do a very specific thing.
Create a class variable to hold the previously selected value for the list. When the form gets created, set the selected item for the list and initialize the previously selected value. Add a changed event handler to the list and use it to maintain the previously selected value. Use the previously selected value to react as appropriate for your problem - in this case whenever the user changes from "3".
Assuming this is a ListBox_SelectionChanged event, you can do it this way.
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
foreach(var item in e.RemovedItems)
{
if (item.ToString() == 3)
{
//do things
}
}
}
Related
I'm running into very strange WinForms behavior that seems to be a framework bug.
Situation:
On an empty form, put 2 ListViews next to each other. Disable HideSelection to make the selection visible while the control does not have focus. The View property (details, large icon) does not seem to matter, but I find details makes it easier to click (in which case, add one column).
It also does not matter whether or not MultiSelect is enabled or not.
(button1 is not involved)
In the form constructor, put some items into the lists:
this.listView1.Items.Add("item1-1");
this.listView1.Items.Add("item1-2");
this.listView1.Items.Add("item1-3");
this.listView2.Items.Add("item2-1");
this.listView2.Items.Add("item2-2");
Now, when the user selects something in listView1, we want the item with the same list index to become selected in listView2. E.g. user selects item1-1 in the left list view, we want to select item2-1 in the right list view and so on.
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
// (*1)
this.listView2.SelectedIndices.Clear();
if (this.listView1.SelectedIndices.Count != 0 && this.listView1.SelectedIndices[0] < this.listView2.Items.Count)
{
// (*1) can also be put here; it makes no difference with regards to the bug (it makes a functional difference though)
this.listView2.SelectedIndices.Add(this.listView1.SelectedIndices[0]);
}
}
The bug sometimes occurs in the following scenario (I can only reproduce if I carry these steps out very quickly (as in, less than a second overall)):
Click item 1 (starting to count at 1) in left list
Item 1 in right list becomes selected automatically
Click item 1 in right list
Click item 2 in left list
Item 2 in right list becomes selected automatically
Click item 2 in right list
Click item 1 in left list
Item 1 in right list becomes selected automatically
Wait a while (ca. 300 ms)
Item 2 in right list becomes selected automatically (Incorrect!)
More generally (this is my conjecture):
Click an item in the left list
Click the item in the right list which just got automatically selected
Quickly select a different item in the left list
The correct item is automatically selected in the right list for a brief moment
The selection jumps back to the previous item after a short delay
I can also observe the invalid selection change in the right list with this event handler, but I can't get any use out of the breakpoint - there doesn't seem to be anything suspicious to me. In the faulty case, the call stack only contains framework internal methods (except for the topmost frame, which is the event handler, of course), so the bogus selection change comes from the framework itself.
private void listView2_SelectedIndexChanged(object sender, EventArgs e)
{
if (this.listView1.SelectedIndices.Count == 0 || this.listView2.SelectedIndices.Count == 0)
{
return;
}
if (this.listView2.SelectedIndices[0] != this.listView1.SelectedIndices[0])
{
// Unless the user MANUALLY selects a DIFFERENT item in the right list view, this should never happen, but it does!
int j = 5; // BREAKPOINT HERE
}
}
The bug does not always happen and seems to be rather timing sensitive, but after some "practice" I can reproduce it about 50 % of the time now.
My guess is that there's some really dumb failsafe mechanism in there. When the user clicks on an item, WinForms just decides to check a short while later if that item really got selected, and if it's not selected, it selects it again (even though the selection was changed programmatically in the meantime). But that alone can't be it, because the bug does not occur unless you explicitly click on the automatically selected item right after the selection changed automatically.
Can anyone reproduce this, and how could I work around this?
This happens to me on Win 10 x64, with .NET frameworks 4.5.2 and 4.7
It turns out you have to set the "focused item" as well, either via ListViewItem.Focused or ListView.FocusedItem, e.g.:
this.listView2.SelectedIndices.Clear();
if (this.listView1.SelectedIndices.Count != 0 && this.listView1.SelectedIndices[0] < this.listView2.Items.Count)
{
var item_we_want_to_select = this.listView2.Items[this.listView1.SelectedIndices[0]];
item_we_want_to_select.Selected = true;
item_we_want_to_select.Focused = true;
}
However all this sounds fishy and I would not use a ListView for such a GUI again. I cannot comfortably tell (nor quote the documentation) about what any of that exactly does, whether it is the correct approach, and whether it has any unintended side effects. It stills seems to me as if the original observation is a Windows bug and this is a workaround that may or may not work.
I have a Combo Box that I can already add items to and I want to be able to remove the item I have selected when I hit the delete key.
Here is the code I am using now.
private void commandComboBox_KeyDown(object sender, KeyEventArgs e)
{
var myComboBox = (ComboBox)sender;
string text = myComboBox.Text;
if (e.KeyCode == Keys.Enter)
{
myComboBox.Items.Add(myComboBox.Text); // Add
}
if (e.KeyCode == Keys.Delete)
{
myComboBox.Items.Remove(myComboBox.SelectedItem);
}
}
When I click in the combobox and start typing and then hit enter I hear a windows sound (not sure which one) and then the item is added to the list.
When I hit the dropdown button I see the item there with the text I entered above. When I hit delete the item goes away (at least I think it does) and then when I click somewhere else I get this exception
System.ArgumentOutOfRangeException: InvalidArgument=Value of '0' is not valid for 'index'.
Parameter name: index
Also when I hit the dropdown button I still see the empty spaces
So my question is how do I properly delete items from a ComboBox :)
Also if there is something better then a ComboBox for this kind of thing plz mention them as well, TY
The Windows sound you hear is actually an error beep. Combo boxes do not accept enter key presses, so it's beeping at you "no!" Your code also runs, of course, adding the item, but that doesn't change the fact that the combo box considers you pressing Enter when it has the focus to be an error. If you are intent on the current design, you need to eat the Enter key press after you've received it so that the combo box doesn't go on to try to process it. To do so, set e.SuppressKeyPress to true.
The exception you get is because you've deleted all of the items in the combo box, but some other section of your code tries to get the text of item #0 (the first item). There is no first item because you deleted it, so an exception is thrown. I'm not sure what code it is that's responsible for this, since I can't see it, but I'm guessing you have written a handler for something like the SelectedIndexChanged event.
Indeed, this is a very unusual interface. The purpose of a combo box is to present the user with a list of choices, not to allow them to type in multiple choices. If you want that, use a multi-line text box. At least that way, they'll be able to see all the things that they've entered.
Or, you could use the classic interface idiom for this, where there is a textbox to type into that works with an Add button to add the typed text to a ListBox control. A Delete button deletes the currently selected item in the ListBox. A Clear button clears all of the items in the ListBox. Yes, it is as confusing to use as it is to explain. Avoid these whenever possible. They were more popular in the bad old days of UI design.
Also when I hit the dropdown button I still see the empty spaces
These aren't actually empty spaces. Well, they are, but not really. :-) What I mean is that they are not placeholders representing individual "empty" items. That's just what you see when the entire combo box is empty (contains no items). Because it contains no items, it can't auto-size the height of its drop-down window, so it uses a fixed size.
I had same problem with ComboBox. Noticed that error occurs only if user hits somewhere else after removing the item but not selecting a new one. Solved it by adding selection of new item after removal. Also handled last item as special case. See working code below:
private void comboBox1_KeyDown(object sender, KeyEventArgs e)
{
ComboBox comboBox = sender as ComboBox;
switch (e.KeyCode)
{
case Keys.Delete:
if ((comboBox.DroppedDown) && (comboBox.SelectedItem != null))
{
if (comboBox.Items.Count == 1) // Removing Last Item
{
comboBox.DroppedDown = false;
comboBox.Text = string.Empty;
comboBox.Items.Clear();
}
else
{
comboBox.Items.Remove(comboBox.SelectedItem);
comboBox.SelectedIndex = comboBox.Items.Count - 1;
}
e.Handled = true;
}
break;
}
}
In my program, I want to put user-entered data into a category, based on what they selected in the COMBOBOX.
There are four categories, and four DATAGRIDVIEWS that are within a TABCONTROL (on a separate form).
I'm able to add the information a user entered, but the COMBOBOX doesn't have it's functionality yet.
How do I make it so that if the user selects "category 1", it sends the data they entered into dataGridView1, "category 2" to dataGridView2?
I know this will require "if, else-if" statement, but I'm not sure as to how to direct the data based on the COMBOBOX selection to the appropriate DGV.
I would make the ComboBox a required field on the entry form. When the user submits the entry, it should be routed to the proper category. Use the ComboBox.SelectedIndex (or .SelectedText or .SelectedValue) to determine which category was selected. The ComboBox.DropDownStyle should probably be DropDownList so the user has to select from the listed options.
If the categorization happens after the entry, then you should have an Apply or Categorize button that performs the actual categorization. The logic is pretty simple:
private void CategorizeButton_Click(object sender, EventArgs e)
{
switch (CategoryComboBox.SelectedIndex)
{
case 0: // Category 1
// Code to send to Category 1
break;
case 1: // Category 2, repeat as necessary
// Code to send to Category 2
break;
default:
MessageBox.Show("Please select a category!");
CategoryComboBox.Focus();
return;
}
}
This can be refactored and simplified if the code to send to the categories is almost identical. Then you can use the SelectedIndex to identify the target DataGridView instead and reduce the code length and repitition.
Would this be a better or valid way to do it:
if(combobox1.SelectedValue = "category1"){
//user-entered info goes to DGV1
else if(combobox1.SelectedValue = "category2")
//user-entered info goes to DGV2
//.etc.
My overall goal is to be able to have a drop down list, and when a value is selected in the drop down list I will be able to select specific values to that option in drop down list 2 and so on. Eventually displaying unique results in Grid View.
For Example,
DropDown List 1
Cars
Food
Colors <- Selected Value
DropDown List 2
Red
Blue <- Selected Value
Black
Grid View Results
Specific Colors Number Available
Baby Blue 2
Night Blue 5
Sky Blue 0
Dark Blue 3
If I'm understanding what you want to do correctly, you could set the initial value to in DropDownList1 to none, and then create an event to handle the SelectedIndexChanged event for DropDownList1, which could switch based on the index selected. For example:
<asp:DropDownList runat="server" ID="DropDownList1" AutoPostBack="True" OnSelectedIndexChanged="DropDownList1_OnSelectedIndexChanged"> put all your list items </asp>
An then in your code behind file:
protected void DropDownList1_OnSelectedIndexChanged(object sender, EventArgs e)
{
List<string> elements; // a List containing the elements you want in the second drop own menu (you will need one for each possible set of elements)
switch(DropDownList1.SelectedValue)
{
case "Colors":
DropDownList2.Items.Clear();
DropdownList2.Items.Add(elements);
break;
// And then your other cases here
}
}
And then do a similar function call when an index is selected on DropDownList2 to set your gridview.
If I understand you correctly, you want to have a first dropdown to choose a category and then a second one to choose a value within that category. If your data is bound then a good way to do this would be to have a converter on the ItemSource of the second dropdown. That converter will take a property that the first dropdown sets and use that to decide which options to show.
You will have something like this:
ComboBox1 -> Category
Category -> value list -> ComboBox2
I don't have any of your code to reference or give you examples for but here is a pretty good tutorial on something similar: http://sekagra.com/wp/2013/04/dynamic-itemssource-for-combobox-in-a-datagrid/
I'm working on a custom control that internally uses a ComboBox.
My problem is when the ComboBox is focused and has the drop-down open, it appears to focus the entire control. I would like to automatically highlight the first item in the drop drown, but right now you have to push the Down key to do so.
Is there a way to programmatically Highlight the first item in a ComboBox (set the readonly IsHighlighted property to true)? I believe the concept of IsHighlight within a ComboBox is different than Focus. Also, I am binding via ItemsSource, so I have no reference to ComboBoxItems.
Here's a way of doing it, although it might not cover all the cases - but you didn't provide too many details (for example, what happens when there is already an element selected? Do you still want to select the first element in the list? The code below will highlight the first element only when there is no selection in the combobox. To make it always select the first element, the DropDownOpened event should be handled too).
public MainWindow()
{
InitializeComponent();
combobox.ItemContainerGenerator.StatusChanged += new EventHandler(ItemContainerGenerator_StatusChanged);
}
void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
if (combobox.ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
{
(combobox.ItemContainerGenerator.ContainerFromIndex(0) as ComboBoxItem).Focus();
}
}
(Hope I understood correctly and this is what you want to do).
It might not be what you are looking for but if you set mycombo.SelectedIndex = 0 then mycombo.IsDropDownOpen = True it should open it up and have the first item selected. It will be highlighted but will also be the value in the combobox as well. I'm not sure if this is not the desired effect though..