Hide item from Combobox temporarily - c#

I was wondering if there was a way to temporarily hide or remove an item from a combo box that is being populated from a database?
I have two combo boxes that are being populated by the same column (To and From Machine Number)
You can't really have Motor1 connected to Motor1, and short of having to repopulate an entire combo box with each selection, I was thinking there has to be a way to temporarily hide the same selection from the second combobox.
Please let me know if you need information on how the comboboxes are being populated(code etc.)
EDIT Here is the population code for the combo boxes:
void PopulateCreateView(CableID_CreateView CView)
{
// Creates a new Model, and gets data from the Db.
CModel = new CableID_Model();
CModel.CNId = 1;
Database_Facade.Operation_Switch(OPREAD);
// Populates the form with data for the Plant Area Codes, Supplier Info and Major Equipment.
foreach (PlantAreaCode_Model Model in PlantAreaCode_Controller.PList)
{
CView.cmbAreaCode.Items.Add(Model.AreaName);
CView.lblDummy.Text = Model.AreaName;
if (CView.lblDummy.Width > CView.cmbAreaCode.DropDownWidth)
{
// Sets the width +20 to allow for the scroll bar.
CView.cmbAreaCode.DropDownWidth = CView.lblDummy.Width + 20;
}
}
foreach (SupplierID_Model Model in SupplierID_Controller.SList)
{
if (Model.CondConfig != null) { CView.cmbXsec.Items.Add(Model.CondConfig); }
if (Model.Insulation != null)
{
CView.cmbInsulation.Items.Add(Model.Insulation);
CView.lblDummy.Text = Model.Insulation;
if (CView.lblDummy.Width > CView.cmbInsulation.DropDownWidth)
{
// Sets the width +20 to allow for the scroll bar.
CView.cmbInsulation.DropDownWidth = CView.lblDummy.Width + 20;
}
}
}
foreach (MajorEquipment_Model Model in MajorEquipment_Controller.MeList)
{
CView.cmbFromLoc.Items.Add(Model.EqipmentNumber);
CView.cmbToLoc.Items.Add(Model.EqipmentNumber);
}
}
Here is the code for the MySQL Query:
public void GetCableId(CableID_Model CModel)
{
DbConnect();
try
{
MajorEquipment_Controller.MeList = new List<MajorEquipment_Model>();
mySqlCommand = mySqlConnect.CreateCommand();
mySqlCommand.CommandText = "SELECT * FROM MajorEquipment;";
mySqlReader = mySqlCommand.ExecuteReader();
while (mySqlReader.Read())
{
MajorEquipment_Controller.MeList.Add(new MajorEquipment_Model
{
EqipmentNumber = Convert.ToString(mySqlReader["EquipmentNumber"])
});
}
mySqlReader.Close();
mySqlCommand.ExecuteNonQuery();
}
catch (MySqlException e) { MessageBox.Show(e.Message); }
finally
{
if (mySqlConnect != null)
{
mySqlConnect.Close();
}
}
}

Unfortunately there is no simple way to keep a ListBox / ComboBox item hidden.
What you can do is simplfy the logic you are using to Load item onto the List. Since both the ComboBox are list of machines that are bound to be dependent on each other
To keep a hidden item you have to create your custom controls that only renders the visible item from collection.

A pseudocode solution would be
On DropDownListChange
Get Selected Item
for all other drop down lists
restore items from backup
if selected value is not default
remove current item from list box

Related

Moving Item In Observable Collection resets moved item to default values

I have a Listview that contains Comboboxes, a textbox, and a check box. I can add multiple rows, and each time a row is added you get a new row in the list view that contains all 5 of those items. I have a default prepended to the beginning of each of the Comboboxes to prompt the user to select a value from the dropdownlist that it is bound to. The problem is when I try to reorder the rows the move event resets all the values to their default values, clears out the textbox and unchecks the check box.
public ObservableCollection<RemovePunctuationRules> PunctuationRules
{
get
{
return _punctuationRules ?? (_punctuationRules = new ObservableCollection<RemovePunctuationRules>());
}
set
{
_punctuationRules = value;
}
}
private void MenuItemMoveUp_OnClick(object sender, RoutedEventArgs e)
{
var selectedIndex = ListView.SelectedIndex;
if (ListView.SelectedIndex > 0)
{
var itemToMoveUp = PunctuationRules[selectedIndex];
PunctuationRules.RemoveAt(selectedIndex);
PunctuationRules.Insert(selectedIndex - 1, itemToMoveUp);
ListView.SelectedIndex = selectedIndex - 1;
}
}

Delete selected item from listbox with button from window form

I have a listbox and i want to select and item in it and press a button to delete that from the database. I can edit and save fine just not delete.
Current code:
private void button1_Click_3(object sender, EventArgs e)
{
if (listBox1.Items.Count >= 1)
{
if (listBox1.SelectedValue != null)
{
listBox1.Items.Remove(listBox1.SelectedItem);
System.Windows.Forms.MessageBox.Show("Item Deleted");
}
}
else
{
System.Windows.Forms.MessageBox.Show("No ITEMS Found");
}
}
I am getting the error:
Items collection cannot be modified when the DataSource property is set.
private void button1_Click_3(object sender, EventArgs e)
{
if (listBox1.Items.Count >= 1)
{
if (listBox1.SelectedValue != null)
{
var items = (List<YourType>)listBox1.DataSource;
var item = (YourType)listBox1.SelectedValue;
listBox1.DataSource = null;
listBox1.Items.Clear();
items.Remove(item);
listBox1.DataSource = items;
}
}
else
{
System.Windows.Forms.MessageBox.Show("No ITEMS Found");
}
}
This will work
Assuming there can be multiple items selected on the ListBox. Below logic will remove from the UI. Also, you can add logic to remove the items from the database if required.
Below exception occurs when Data Bindings are different than data sources.
Items collection cannot be modified when the DataSource property is
set
A data source specifies the source of data whereas data bindings define how data is bound to once it is retrieved. Typically, data binding occurs only during UI initialisation, and it doesn't change after that.
The data source itself can change over the life of control, but this is rare.
Here, the data source elements change.
On to your actual error. You cannot set DataSource and modify the Items property. It isn't allowed. The correct way to handle this is to add the items to your data source. This insertion in your data source will cause the control to update the list automatically. The ListBox Control relies on the DS to store the data so all changes must go through that. In the rare case where you need to be able to edit the Items directly then, you'll have to do away with DataSource and manually populate the Items collection. This update to DataSource usually is not needed though.
Below code to reset the data source
if(listBox1.SelectedItems != null)
{
// Assuming its List of string
var items = listBox1.DataSource as List<string>;
// Remove multiple selected items
var count = listBox1.SelectedItems.Count;
while(count != 0)
{
var selectedItem = listBox1.SelectedItems[count-1];
if(items.ContainsKey(selectedItem))
{
items.Remove(selectedItem);
}
count--;
}
listBox1.DataSource = null;
listBox1.Items.Clear();
listBox1.DataSource = items;
}
An optimised approach to store the data source and modify it to update the data source directly. Use the ObservableCollection type and update the collection to update the UI.
public class NamesClass : DependencyObject
{
public ObservableCollection<string> Names {get; private set; }
public TestClass()
{
this.Names = new ObservableCollection<string>();
}
}
Now include the DependencyObject class as DataSource and update the Names collection.

Deleting multiple checked items from an SQL bound checklist

So right now, I have tried the following code, however it only removes one list item. It seems that after it deletes the first item, the list refreshes and the other checked item does not get deleted. How can I go around this so that all the checked items are deleted from the DB Table?
//NewFoodInputTextBox is an ASP.NET TextBox which takes input
//just fine and outputs status/error updates as well.
protected void DeleteFoodButton_Click(object sender, EventArgs e)
{
try
{
int delCount = 0;
int prevDelCount = 0;
string status = "";
foreach (ListItem Item in FoodChecklist.Items)
{
if (Item.Selected)
{
FoodList.Delete(); //only deletes 1 item
prevDelCount = delCount;
delCount += 1;
if (delCount > prevDelCount) //printing out the deleted items
{
status = status + " " + Item.ToString(); //returns all checked items normally
}
}
}
if (delCount == 0)
{
NewFoodInputTextBox.Text = "Nothing selected to delete";
}
else
{
NewFoodInputTextBox.Text = "Deleted the following: " + status;
}
}
catch
{
NewFoodInputTextBox.Text = "Unexpected behavior detected";
}
}
Your problem is that you are using the Selected items, and not the Checked ones. These are 2 different things (selected is the blue highlight, checked is the checkbox). Use the Checked property in your condition and everything should work fine.
Side note, you could also use the CheckedItems property of the ListView in your foreach to simplify your code.
foreach (ListItem Item in FoodChecklist.CheckedItems)

ListBox deletion

I have a listbox, with 2 buttons, new and delete. new adds an item into the list box, and the delete button should delete the item out of the list box. The list box items are tied to a class that stores user entered data from text boxes below.
private void AddListBox()
{
lstCondition.BeginUpdate();
Condition cond = new Condition("");
cond.Name = string.Format("Condition {0}", _selection.NetConditions.Count + 1);
_selection.NetConditions.Add(cond);
lstCondition.EndUpdate();
lstCondition.SelectedItem = cond;
cboNetCondition.Properties.Items.Clear();
cboNetCondition.Properties.Items.AddRange(NetCondition);
cboControlType.Properties.Items.Clear();
cboControlType.Properties.Items.AddRange(ControlType);
cboFlowRate.Properties.Items.Clear();
cboFlowRate.Properties.Items.AddRange(FlowRate);
}
private void btnNew_Click(object sender, EventArgs e)
{
AddListBox();
}
the cbo items are comboboxes, whose data gets tied in the condition class to each instance of the list box.
public frmNetConditions(Condition condo, Selection selection)
{
InitializeComponent();
_selection = selection;
lstCondition.DataSource = _selection.NetConditions;
condition = _selection.NetConditions.Count;
}
private void btnDelete_Click(object sender, EventArgs e)
{
selectedCondition = (Condition)lstCondition.SelectedItem;
cboControlType.SelectedIndex = -1;
cboNetCondition.SelectedIndex = -1;
cboFlowRate.SelectedIndex = -1;
txtFlowRate.Text = string.Empty;
txtStatPressure.Text = string.Empty;
txtDampOpening.Text = string.Empty;
txtDensity.Text = string.Empty;
cboDensity.SelectedIndex = -1;
lstCondition.Items.Remove(lstCondition.SelectedItem);
lstCondition.Refresh();
}
After pressing this delete button, the listbox, still contains the item i wish to delete, im unsure why thats the case?
Update with datasource
public List<Condition> NetConditions { get { return _netconditions; } }
As already suggested, you should bind to a BindingList<Condition> instead of a List<Condition>. This allows you to change the datasource and the control (ListBox) to get notified by your changes. The code should look like this:
lstCondition.ValueMember = "ConditionId";
lstCondition.DisplayMember = "Name";
lstCondition.DataSource = NetConditions;
After defining the binding, the correct way of operating on the ListBox items is to remove from the datasource, not the ListBox itself:
// SelectedItem should be checked for null (no selection is an option)
NetCondition.Remove((Condition)lstCondition.SelectedItem);
However, if you plan to change properties from an element (so, not the list itself), the control is notified only if your element (Condition) implements INotifyPropertyChanged interface.

How to get id of the selected item in combobox and populate another combobox with it?

I have 2 comboboxes created with Ajax Toolkit. One of them has a list of systems. I wanted to fill the other combobox with a list of subsystems whenever a system is selected. I did not use DisplayMember or ValueMember and most examples are using them.
.aspx side just in case:
<ajaxToolkit:ComboBox ID="cbox1" runat="server" OnSelectedIndexChanged="cbox1_SelectedIndexChanged" />
Is this doable with what I'm trying? Is the event I used correct for the situation?(I guess not,but other events seem to be unrelated) Let me show you the code:
protected void fillSystemCombo()
{
var sysOperations = new ModelOperations.ConstantSystem.ConstantSystemOperations();
var sys = sysOperations.GetSystemList().TransactionResultList;
foreach (var item in sys)
{
cbox1.Items.Add(item.description);
}
}
This works fine and I can see the systems in my first combobox.
This is what I tried for populating the second one:
protected void cbox1_SelectedIndexChanged(object sender, EventArgs e)
{
var subSysOperations = new ModelOperations.ConstantSubSystem.ConstantSubSystemOperations();
int index = Convert.ToInt32(cbox1.SelectedItem.Value);//i think this should get the id...
var subsys = subSysOperations.GetSubSystemList().TransactionResultList;
foreach (var item in subsys)
{
if (item.sysID == index)
{
cbox2.Items.Add(item.description);
}
}
}
sysID is the foreign key in SubSystem which is the ID of System. By the way, my SelectedIndexChanged event never fired when I was debugging the program even though I clicked on an item in combobox.
I've actually found the answer after carefully reading the parameters taken by Items.Add. It wants a ListItemso if I create a ListItem inside the loop I can finally add my items with both a Text and a Value like this:
foreach (var item in sys)
{
combo1.Items.Add(new ListItem { Text = item.description, Value = item.ID.ToString() });
}
After that I can get the index with
int index = Convert.ToInt32(combo1.SelectedValue);

Categories