I'm trying to create a selection for roomType but why some controls are showing even its not equal on Combobox text here is my code in Combobox
private void cbRoomType_SelectedIndexChanged(object sender, EventArgs e) {
GenerateDynamicUserControl();
foreach (Control c in flowLayoutPanel1.Controls)
{
if (c.GetType() == typeof(CustomerControl))
{
CustomerControl customerControl = (CustomerControl)c;
if (!customerControl.RoomType.ToLower().Contains(cbRoomType.Text.ToLower()))
{
flowLayoutPanel1.Controls.Remove(c);
}
}
}
}
Im expecting to solve my problem
You are committing the cardinal sin of modifying the collection while iterating over it with a foreach.
Add all your matches to a separate list and then remove them afterwards:
private void cbRoomType_SelectedIndexChanged(object sender, EventArgs e) {
GenerateDynamicUserControl();
List<CustomerControl> matches = new List<CustomerControl>();
foreach (Control c in flowLayoutPanel1.Controls)
{
if (c.GetType() == typeof(CustomerControl))
{
CustomerControl customerControl = (CustomerControl)c;
if (!customerControl.RoomType.ToLower().Contains(cbRoomType.Text.ToLower()))
{
matches.Add(c);
}
}
}
foreach(var c in matches) {
flowLayoutPanel1.Controls.Remove(c);
}
}
Related
I have a textbox that I can use to search for items and subitems in a listview. Once matches are found the BG colour of the items changes. This works fine, but when I delete the entry from the textbox the items and subitems still remain highlighted until I enter another search.
I am not sure if it is the event that I am using or if it is a problem with my logic. I want the items to be highlighted dynamically as the user types in the search but if they delete the entry I want the BG colour to change back to white.
private void txtSearchMenu_TextChanged(object sender, EventArgs e)
{
string searchVal = txtSearchMenu.Text.ToLower();
if (searchVal != "")
{
foreach (ListViewItem item in lvMenuItems.Items)
{
foreach (ListViewItem.ListViewSubItem subSearch in item.SubItems)
{
if (subSearch.Text.ToLower().Contains(searchVal) == true)
{
subSearch.BackColor = Color.MediumAquamarine;
}
else
{
subSearch.BackColor = Color.White;
}
}
item.UseItemStyleForSubItems = false;
}
}
}
when I delete the entry from the textbox the items and subitems still remain highlighted until I enter another search
This is because you do nothing if textbox is blank.
Move check for empty string inside foreach like this:
private void txtSearchMenu_TextChanged(object sender, EventArgs e)
{
string searchVal = txtSearchMenu.Text.ToLower();
foreach (ListViewItem item in lvMenuItems.Items)
{
foreach (ListViewItem.ListViewSubItem subSearch in item.SubItems)
{
// move condition here
if (searchVal != "" && subSearch.Text.ToLower().Contains(searchVal) == true)
{
subSearch.BackColor = Color.MediumAquamarine;
}
else
{
subSearch.BackColor = Color.White;
}
}
item.UseItemStyleForSubItems = false;
}
}
As Sintar said:
private void txtSearchMenu_TextChanged(object sender, EventArgs e)
{
string searchVal = txtSearchMenu.Text.ToLower();
if (searchVal != "")
{
foreach (ListViewItem item in lvMenuItems.Items)
{
foreach (ListViewItem.ListViewSubItem subSearch in item.SubItems)
{
if (subSearch.Text.ToLower().Contains(searchVal) == true)
{
subSearch.BackColor = Color.MediumAquamarine;
}
else
{
subSearch.BackColor = Color.White;
}
}
item.UseItemStyleForSubItems = false;
}
}
else
{
foreach (ListViewItem item in lvMenuItems.Items)
{
foreach (ListViewItem.ListViewSubItem subSearch in item.SubItems)
{
subSearch.BackColor = Color.White;
}
}
}
}
I have been searching for this answer for a while with no luck. It seems like a fairly simple question but I can't come up with anything, so here goes:
I want to set all the controls in all of my tabs to ReadOnly = true or Enabled = false (or the reverse).
I'm using this code:
public void readOnly(bool read)
{
if (read == true)
{
foreach (var c in mainTab.Controls)
{
if (c is TextBox)
{
((TextBox)c).ReadOnly = true;
}
if (c is CheckBox)
{
((CheckBox)c).Enabled = false;
}
Etc. ......
How can I apply changes to all tabs, not just mainTab, without repeating the code? I'm new to programming so I apologize if I'm missing something obvious...
If this question has already been answered could you kindly point me to the page?
To access all tabs, you can use the TabPages property of the TabControl. Further, you can significantly simplify your code:
public void SetReadOnly(bool readOnly)
{
foreach (TabPage tab in tabControl.TabPages)
{
foreach (Control c in tab.Controls)
{
if (c is TextBox)
{
((TextBox)c).ReadOnly = readOnly;
}
else
{
// All controls support this property
c.Enabled = !readOnly;
}
}
}
}
You could create a method that will loop through the controls of each tab page in your tab control and set the Enabled property of the controls, and have a Boolean argument that says what the value should be:
private void SetTabControlEnabled(bool enabled)
{
foreach (TabPage tabPage in tabControl1.TabPages)
{
foreach (Control control in tabPage.Controls)
{
control.Enabled = enabled;
}
}
}
Then, as an example, you could call this method and pass true to enable the controls or false to disable them:
private void btnEnable_Click(object sender, EventArgs e)
{
SetTabControlEnabled(true);
}
private void btnDisable_Click(object sender, EventArgs e)
{
SetTabControlEnabled(false);
}
You need a recursive function:
public static void EnabledDisabeldControls(System.Windows.Forms.Control.ControlCollection paramControls, bool enabled)
{
foreach (System.Windows.Forms.Control c in paramControls)
{
if (c is TextBox)
{
((TextBox)c).ReadOnly = !enabled;
}
if (c is CheckBox)
{
((CheckBox)c).Enabled = enabled;
}
EnabledDisabeldControls(c.Controls, enabled);
}
}
I am really confused on thinking which control to use for my purpose.
I am having list of items say item1 to item10. User can select 4 or 5 items in any order.
Now user selected items has to be separated in same order.
For example, if the user selected the items in following order, item4, item8, item3 and item2.
I want it in the same order. item4,item8,item3,item2.
How do I achieve this in winforms control?
It is not a very nice solution but I wrote it as you asked.
Set the SelectionMode of your ListBox to MultiExtended or MultiSimple as you need.
Then write this code in SelectedIndexChanged event of your ListBox:
List<string> orderedSelection = new List<string>();
bool flag = true;
private void listBox3_SelectedIndexChanged(object sender, EventArgs e)
{
if (flag)
{
flag = false;
var list1 = listBox3.SelectedItems.Cast<string>().ToList();
if (listBox3.SelectedItems.Count > orderedSelection.Count)
{
orderedSelection.Add(list1.Except(orderedSelection).First());
}
else if (listBox3.SelectedItems.Count < orderedSelection.Count)
{
orderedSelection.Remove(orderedSelection.Except(list1).First());
}
var list2 = listBox3.Items.Cast<string>().Except(list1).ToList();
listBox3.Items.Clear();
for (int i = 0; i < list1.Count; i++)
{
listBox3.Items.Add(list1[i]);
listBox3.SelectedIndex = i;
}
foreach (string s in list2)
{
listBox3.Items.Add(s);
}
flag = true;
}
}
When user selects an item, It comes to first of the list and the rest of the items comes next.
Also, there is an alternative way. You can use a CheckedListBox with two extra button for moving selected items up and down. So user can change the order of selected items.
This solution uses CheckListBox's ItemCheck event along with a private List to keep track of the click items order.
protected List<string> clickOrderList = new List<string>();
private void Form1_Load(object sender, EventArgs e)
{
// Populate the checked ListBox
this.checkedListBox1.Items.Add("Row1");
this.checkedListBox1.Items.Add("Row2");
this.checkedListBox1.Items.Add("Row3");
this.checkedListBox1.Items.Add("Row4");
}
private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
if (sender != null && e != null)
{
// Get the checkListBox selected time and it's CheckState
CheckedListBox checkListBox = (CheckedListBox)sender;
string selectedItem = checkListBox.SelectedItem.ToString();
// If curent value was checked, then remove from list
if (e.CurrentValue == CheckState.Checked &&
clickOrderList.Contains(selectedItem))
{
clickOrderList.Remove(selectedItem);
}
// else if new value is checked, then add to list
else if (e.NewValue == CheckState.Checked &&
!clickOrderList.Contains(selectedItem))
{
clickOrderList.Insert(0, selectedItem);
}
}
}
private void ShowClickOrderButton_Click(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder();
foreach (string s in clickOrderList)
{
sb.AppendLine(s);
}
MessageBox.Show(sb.ToString());
}
I am trying to move multiple selected item from one ListBox to another ListBox using this code
protected void imgbtnMoveRightListBox_Click(object sender, ImageClickEventArgs e)
{
foreach (var item in lstboxSkill.SelectedItem)
{
lstBBoxSkill2.Items.Add(item);
}
}
but it shows an error
foreach statement cannot operate on variables of type
'System.Web.UI.WebControls.ListItem' because
'System.Web.UI.WebControls.ListItem' does not contain a public
definition for 'GetEnumerator'
I don't know why this error occured.
Please help me to fix it
Check this code.
protected void imgbtnMoveRightListBox_Click(object senderImageClickEventArge)
{
foreach (ListItem item in lstboxSkill.Items)
{
lstBBoxSkill2.Items.Add(item);
}
}
Please check this snap shot I have created and its working fine.
and the code behind code is given below:
protected void Page_Load(object sender, EventArgs e)
{
lstboxSkill.Items.Add("ASP.Net");
lstboxSkill.Items.Add("C#");
lstboxSkill.Items.Add("AJAX");
lstboxSkill.Items.Add("JavaScript");
lstboxSkill.Items.Add("HTML");
lstboxSkill.Items.Add("HTML5");
lstboxSkill.Items.Add("JQuery");
}
protected void imgbtnMoveRightListBox_Click(object sender, EventArgs e)
{
foreach (ListItem Item in lstboxSkill.Items)
{
if (Item.Selected == true)
{
lstBBoxSkill2.Items.Add(Item);
}
}
}
This is because the SelectedItem property returns only the item with the lowest index out of the list of items selected. You should change your code as
protected void imgbtnMoveRightListBox_Click(object sender, EventArgs e)
{
foreach (ListItem Item in lstboxSkill.Items)
{
if (Item.Selected == true)
{
lstBBoxSkill2.Items.Add(Item);
}
}
}
And set both listbox SelectionMode="Multiple".
Hope this will help you. Don't forget marked as answer
Thanks
Solomon S.
lstboxSkill.SelectedItem is a ListItem, which is neither an array nor an object collection that implements the System.Collections.IEnumerable<T> or System.Collections.Generic.IEnumerable<T> interface, so it's not possible to do foreach against it.
I think this is what you're looking for:
foreach (var item in lstboxSkill.Items)
{
if (item.Selected)
{
lstBBoxSkill2.Items.Add(item);
}
}
protected void imgbtnMoveRightListBox_Click(object sender, EventArgs e)
{
lbltxt.Visible = false;
if (ListBox1.SelectedIndex >= 0) // in this we are checking whether a single item is clicked.
{
for (int i = 0; i < ListBox1.Items.Count; i++) // we are looping through the list box items
{
if (ListBox1.Items[i].Selected) // finding the selected items
{
if (!arraylist1.Contains(ListBox1.Items[i]))
{
arraylist1.Add(ListBox1.Items[i]); //if found then adding those items to the array list
}
}
}
for (int i = 0; i < arraylist1.Count; i++)
{
if (!ListBox2.Items.Contains(((ListItem)arraylist1[i])))
{
ListBox2.Items.Add(((ListItem)arraylist1[i])); // we are adding the array elements to the second list box
}
ListBox1.Items.Remove(((ListItem)arraylist1[i]));
}
ListBox2.SelectedIndex = -1;
}
else
{
lbltxt.Visible = true;
lbltxt.Text = "Please select atleast one in Listbox1 to move";
}
}
Source
I am having 40 combo-box in my win-form application, I want to check at end on button click that all the combo-box value has been entered i.e no combo-box value has been selected empty
i am trying below code using for each loop but cant find success
foreach (Control c in this.Controls)
{
if (c is ComboBox)
{
ComboBox textBox = c as ComboBox;
if (textBox.SelectedValue==string.Empty)
{
MessageBox.Show("please fill all fields");
}
}
}
so how to achieve this validation in simple lines of codes
Try to use linq and a recursion:
var isAnyEmpty = ScanForControls<ComboBox>(this)
.Where(x => x.SelectedIndex < 0)
.Any();
if (isAnyEmpty)
MessageBox.Show("please fill all fields");
And recursion search:
public IEnumerable<T> ScanForControls<T>(Control parent) where T : Control
{
if (parent is T)
yield return (T)parent;
foreach (Control child in parent.Controls)
{
foreach (var child2 in ScanForControls<T>(child))
yield return (T)child2;
}
}
To make sure that you check each & every ComboBox in your Form you will have to iterate over each control in you Form, Try this for that.
private void button1_Click(object sender, EventArgs e)
{
foreach (Control c in this.Controls)
{
if (c is ComboBox)
{
ComboBox textBox = c as ComboBox;
if (textBox.SelectedValue == null)
{
MessageBox.Show("please fill all fields");
break;
}
}
else
recursiveComboboxValidator(c);
}
}
void recursiveComboboxValidator(Control cntrl)
{
foreach (Control c in cntrl.Controls)
{
if (c is ComboBox)
{
ComboBox textBox = c as ComboBox;
if (textBox.SelectedValue == null)
{
MessageBox.Show("please fill all fields");
break;
}
}
else
recursiveComboboxValidator(c);
}
}