I have a combobox binded to an observable collection through
cmbBladesTab1.ItemsSource = easyRunData.olstBlades;
that works fine.
I want the combobox to be binded to all that values plus one.
E.g.
easyRunData.olstBlades; contains "PL1", "PL2", "PL3", "PL4"
while cmbBladesTab1 contains "ALL BLADES", "PL1", "PL2", "PL3", "PL4"
--ADD all work has to be done from code-behind
Thanks for your help.
You could add a property, that adds the particular item to the list.
ObservableCollection<string> myCollection;
ObservableCollection<string> MyCollectionViewProp
{
get
{
var tempCollection = new ObservableCollection<string>(myCollection);
tempCollection.Add("Extra element");
return tempCollection;
}
}
Depending on the size of the collection and the number of times it is accessed, this is probably the programmatically simplest solution. If you need to access it often, the worse this solution gets, as it creates a new collection every time.
In this case you should probably listen to the CollectionChanged event and keep a separate redundant list.
Easiest way would be to add an extra item in the observable collection with some prefixed text / key.
That way, because it's in the collection, it will be visible in the combobox and when the user selects this item you can evaluate it to see if it's the added item or not.
A good example is indeed given as an answer on this question add an item to combobox before bind data from data base
Related
In a C# WinForms project I'm querying a database to get a list of values to populate a listbox with. The query populates a List and then I iterate through that to add the list items to the listbox.
lsNewValuesList = dbGetNewValueInfo.GetNewValuesDgvData(strNewValuesQuery);
foreach (string strItem in lsNewValuesList)
{
lsBxNewValues.Items.Add(strItem);
}
After that's done, I need to manually add an item to the top of the list, which I'm doing via, lsBoxNewValues.Items.Insert(0, "DELETE");. But when I run it I get the message,
Items collection cannot be modified when the DataSource property is set.
Here is a screenshot of the error (to clarify some questions):
Looking into that I'm understanding that error arises when the listbox is populated with a datasource, but I'm just populating it from a string list. Is that, technically, a datasource then?
How do I accomplish what I'm trying to do?
[UPDATE]
Okay, I've done some fiddling around, albeit without resolving my issue, and I've tried the following:
lsNewValuesList = dbGetNewValueInfo.GetNewValuesDgvData(strNewValuesQuery);
lsNewValuesList.Insert(0, "DELETE");
lsBxNewValues.DataSource = lsNewValuesList;
//foreach (string strItem in lsNewValuesList)
//{
// lsBxNewValues.Items.Add(strItem);
//}
Instead of inserting "DELETE" in the ListBox (which is what I was originally trying and was causing the error), I inserted it at index 0 of the List, the datasource of the ListBox, and then set the ListBox's datasource. "DELETE" is showing up in the ListBox, but it's getting alphabetized along with the rest of the items. I'm not doing any sorting of the list or the ListBox - I'm using ORDER BY in the database query, however. CyberZeus suggested I use Refresh() on the ListBox, but that didn't have any effect.
Yes, a list of strings is a datasource.
You have to add the data retrieved from the database to the datasource of the ListBox. You may need to refresh the ListBox.
I am trying to exchange the items in two ListBox controls, but only the word "(Collection)" is added. Why?
You're adding to a ListBox one element which is a collection of elements, ListBox.ObjectCollection.
The ToString() method is called on this object, returning the object type (Collection).
To swap the items, you could use a temporary storage that holds the collection of items of one ListBox, clear its Items collection, add the items of the second ListBox, clear the second ListBox and add the Items of the first one, using the temporary storage as source:
var itemsL1 = new ListBox.ObjectCollection(listBox1, listBox1.Items);
listBox1.Items.Clear();
listBox1.Items.AddRange(listBox2.Items);
listBox2.Items.Clear();
listBox2.Items.AddRange(itemsL1);
This works if the ListBoxes Items collections is not filled using the DataSource property.
Otherwise, swap the data sources.
Here's my problem: I need to make a DataGrid with dynamic comboboxes using the WPF. If the value of a combobox is already used in the previous rows, the next ones, that will be added by the user, shouldn't contain the item already used.
In this image, the ITEM A shouldn't apear on the combobox of the second line.
I don't have ideia how to accomplish this, can anyone show me a light?
OBS: The DataGrid ItemsSource is binded to an ObservableCollection, and the DataGridComboBoxColumn ItemsSource is a List.
Thanks !!!
The ItemsSource of the combo doesn't have to be bound to an ObservableCollection, but it can help depending on exactly how you solve this.
When that cell goes in to edit mode the property the ItemsSource is bound to gets hit - so you can return a new list of items each time the getter is hit. Here is a very basic example to give you an idea:
public List<string> MyItemsSource
{
get
{
var myNewList = MyMasterList.ToList(); //create a (reference) copy of the master list (the items are not copied though, they remain the same in both lists)
if (PropertyA != null)
myNewList.Remove(PropertyA);
return myNewList;
}
}
So what you are creating and returning is a filtered version of your master list of all possible items. LINQ will be of great help to you here.
Alternatively you could keep just one static copy of the master list as an ObservableCollection, and simply remove items from that static copy as they get selected (and add them back in as they get unselected). Which option you choose will depend on how many times the list can be modified due to items being selected and how complicated it is to generate the list. I've used the dynamically generated list many times in the past, it's an option that works well in most cases.
I have a combo box that is bound to a collection that is essentially a list of Name/Value pairs. The collection can have multiple items with different names, but the values may be the same.
public class NameValuePair
{
public string Name { get; set; }
public string Value { get; set; }
}
public class NameValuePairCollection : List<NameValuePair>
{
public NameValuePairCollection(): base() { }
}
So inside my User Control I have a private field called items which is an instance of that NameValuePair collection:
private NameValuePairCollection items = new NameValuePairCollection()
Somewhere along the lines that collection gets initialized and items get added to it. However, the problem I see is when I try to set the selected index of the combo box that is bound to this collection:
this.CboItemsSelector.SelectedIndex = 3;
or
this.CboItemsSelector.SelectedItem = this.items[3];
The selected item is there but the UI is not synchronized. The UI's selector still defaults to the first item in the list, even thought the SelectedItem's Name and Value properties DO IN FACT CORRESPOND to whatever is in index 3 of the underlying collection!
Any ideas on how to force the ComboBox to refresh itself? Or just plain fix the issue? I know it's quite small issue, but it is big enough to force me to rewrite quite a bit of code.... :( :( :(
Thanks!
You need to inherit from ObservableCollection, not List. Otherwise no OnPropertyChanged events will be fired and the bound control wont know the data has been updated.
Do the selected Item's Name and Value properties match or is the SelectedItem an instance from within the same collection? .Net will not know to compare the items by name and value unless you tell it to, else it will use object equality to try and find the item in your list. If you are setting the selected item to an instance that is not actually in the list (but has the same properties) .net will not find it in the list. You have 2 options, override equality for your object and force comparison of properties, or ensure that you always set the selected item to an item in the list. Also try what Andy May suggested and do 2 way binding on the ItemsSource and on the SelectedItem, should work then
I have a Combobox, in which I would like its items to be the column data that is located on a DataGrid. Is there anyway to set the Combobox itemsource to be a specific column of a DataGrid?
Right now I'm iterating each row of the DataGrid, getting the field's data and adding them to the Combobox, but that means that I would have to clear all the items and reiterate everytime the DataGrid is modified.
You can set ItemsSource and DisplayMemberPath properties:
comboBox1.ItemsSource = dataGrid1.ItemsSource;
comboBox1.DisplayMemberPath = "ColumnName";
I Think you'are taking the wrong approach. Your data grid must be bound to a collection of object. I guess you could just build another collection by extracting the desired fields (for example with linQ) and expose this new collection to your view such that you can bind your combobox.
I you want to keep this second collection updated, make your first main collection an ObservableCollection such taht your can subscribe to CollectionChanged Event. In the event handler, just manage the add and remove in your combobox source collection.