I have plumbed the deeps of my google-fu to find an answer.
First, I am not simply asking how to bind a combobox to a datasource. It's a bit more than that unless I'm having a serious understanding gap.
On my Winform, I have a DataGridview on the left and on the right I have a panel with values from the selected row on the left. One of those controls on the right is the ComboBox I'm having trouble with. I have my bindingsource and dataview set up and the other controls on the right are working splendidly, except the ComboBox control.
The user, interacting with this ComboBox, should see values such as "Item ABC" and "Item EFG" and the value related to them might be 1234 and 5678. If this was a fully unbound control I'd put an object array of items in. Once I get it working, I'd load that from a different source.
But when I try to DataBindings.Add("??", dataview, "dataviewfield", ...) I can't get the proper value for "??". Runtime debug shows that "SelectedItem.Value" would be the right option, but I get "not found" type exception when I use that. I've tried "SelectedValue" as well, but that didn't work (debug show's it's null & throws no nulls allowed exception).
How can I get that value placed directly into the DataView via the Binding?
Setting the .DataSource simply loses the items and doesn't help at all.
How does one do this? Short of making the ComboBox unbound totally, setting the selectedindex directly and capturing the value when the selected index changes changes - Just seems so clunky to have to do that.
-old programmer
Further Notes: I edited to clarify the placement of the ComboBox.
I have made progress (naturally, only after asking a question does a new avenue pop into my head). I got to thinking I might need a custom binding adapter so started googling that. I found some samples doing what I want.
The foremost problem was I was not using assigning a datasource on the ComboBox, I was simply adding items. When I created a two column dataset and a few rows (could have been anything I suppose) and set that and the two field names as the ComboBox's displaymember and valuemember did the SelectedValue start showing a value (instead of null all the time).
I think that was the problem. The remaining issue is getting the left hand side to re-display/refresh after the change.
When loading the datasource for the DataGridView and the bindingsource, try making them share the same list:
BindingSource1.Datasource = dataset
DataGridView.Datasource = BindingSource1
This should mean that any changes to the data in the bindingsource will also update the DataGridView.
To edit the selected object then just handle the SelectionChanged event and set the BindingSource1.Position to the index of the selected object in the Datasource.
In the data grid control, there's an empty row at the bottom. When a user fills the cells, I can store the contents, hence creating an additional element in the database.
However, when the number of pre-existing rows grows large, the user'd have to scroll each time to access that row. Is there a smooth way to move it up to the top?
The solution I can think of is placing other controls in a panel right above the data grid. But that's more work than I'm willing to spend. Still, it'd be nice to let the users not be forced to scroll their mouses off.
Assuming the collection view returned by your DataGrid's Items property implements IEditableCollectionView (which, in my experience, does for an editable DataGrid), then you should be able to use the NewItemPlaceholderPosition property through the explicit interface:
// Assume myDataGrid is the DataGrid control holding your results.
// You can do this inside your window/control's constructor after its
// call to InitializeComponent and after myDataGrid's ItemsSource
// property has been set.
var collView = myDataGrid.Items as IEditableCollectionView;
if( collView != null )
collView.NewItemPlaceholderPosition = NewItemPlaceholderPosition.AtBeginning
I'm using ObjectListView with C# and .Net 4.0. I wrote code that reloads the listview and then re-selects the last selected index.
The re-selection code is quite simple:
olvListView.SelectedIndex = i;
This appears to work, because the item is selected. However, if I then click the up or down arrow, the selection jumps up to the second row (no matter what row I selected), suggesting that the selection was actually set on the first row, no matter what was the value of i.
What am I doing wrong here?
The underlying ListView Control distinguishes between 'selection' and 'focus'.
olvListView.SelectedIndex = i; changes the selection but not the focus. But the focused row is the one that the keyboard input relates to.
Either change the focus the as well
olvListView.SelectedIndex = i;
olvListView.FocusedItem = olvListView.SelectedItems[0];
or call
olvListView.SelectObject(aModelObject);
The second solution would be the preferred way to select an item when working with OLV, however you say you "wrote code that reloads the listview", so the reference to the original item is probably different. Maybe you should just refresh the items that changed, instead of reloading everything. That way you could preserve the selection.
Example if your olv have datasource from "class_z.list" and foreach have only one result.
foreach(class_z a in class_z.list.Where(x=>x.id==id_value))
{
olv.SelectedObject = z;
}
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 am trying to deselect (blank out) a number of combo-boxes in my windows forms application. In my application I have a Reset method that sets the SelectedIndex for each combo to -1. All of my combo-boxes are databound, i.e. each combo-box is populated using a datasource.
I have noticed that sometimes my Reset method works, i.e. it deselects the currently selected item and blanks the combo. However, other times it chooses the first item (SelectedIndex = 0) straight after I attempt to set it to -1. From a users point of view this looks like a bug as it doesn't always "clear" the form.
According to MSDN:
"To deselect the currently selected item, set the SelectedIndex to -1. You cannot set the SelectedIndex of a ComboBox item to -1 if the item is a data-bound item."
Does anyone know of a work around?
Many thanks
Use combination of the void and property
comboBox.ResetText();
//to reset selected value
comboBox.SelectedIndex = -1;
Don't know if anyone is still interested in this, seeing as it's now 5 years later, but I found a very easy workaround. Totally non-intuitive (I only found it by looking at the reference source code), but trivial to implement:
ComboBox1.FormattingEnabled = True;
Yep, that's all there is to it!
If you're curious, you can peruse the source code to see what's going on. It appears that the root cause of the bug noted by #CuppM is the attempt to set the position in the data source:
if (!FormattingEnabled || SelectedIndex != -1) {
this.DataManager.Position = this.SelectedIndex;
}
I would guess that it should have simply been '&&' instead of '||' in the condition, as the code probably shouldn't be setting the Position to an invalid value regardless of the FormattingEnabled property.
In any case, it allows for a simple workaround. And since the default behavior if the 'Format' property is blank is a no-op, you don't have to change anything else. It just works. :-)
(I should note that I have only tried this with .NET 4.7, so I can't say whether it works for prior versions of the .NET Framework.)
You can try to set the Selected Value or Item to null (Nothing in VB)
I cant remember the behavior of throwing an exception. However, I do remember that I used to insert a value called -1, (None) to the combo-box after it was databounded usually through the databind events. I'd recommend get the data in a List and insert the new value to this list. Bind the combo to the List now.
Only the following code works for me, so try:
comboBox.ResetText(); //framework 4.0
ComboBox1.SelectedItem = null;
For anyone still looking at this old post I wanted to add a note from what Hisham answer.
Make sure to clear your list after inserting his code.
comboBox.ResetText();
//to reset selected value
comboBox.SelectedIndex = -1;
comboBox.Items.Clear();
Try assigning null or String.Empty to the SelectedValue property.
If your target framework is 4.0 - here is the solution:
Install .Net Framework 4.5 (do not change target framework of your project, just install the framework).
After installing, that line deselects databound combobox:
combobox.SelectedValue = 0;
My value member is "Id" int primary key auto-increment, so that field does not contain value 0.
However, that won't work on Windows versions, that do not support .net45
Try to set the [ComboBoxObj].SelectedIndex=-1; which will make it to empty value.
-1 refers to deselect or nullify the value of combobox
Thanks
I have had this problem for a while, but if you use:
'ComboBox.ResetText();'
it will make the text "" and leave the items in the combo box unaffected.
i used the following code in my application
private void UpdateComboBox(ComboBox Box, string Group, List<string> Numbers)
{
Box.Items.Clear();
Box.BeginUpdate();
Box.Items.Add("<<Add Contact>>");
foreach (string item in Numbers)
{
if(item != "")
Box.Items.Add(item);
}
Box.EndUpdate();
Box.ResetText();
}
So i run the method last, once all items are in the combo Box.
Try this line of code:
combobox1.Items.clear();
It works for me.
Add to your combobox one empty item, something like this:
cb.Items.Add("");
After this you can deselect your combobox by selecting the last cb item:
cb.SelectedIndex = cb.Items.Count - 1;
There you go!
You'll have the last place empty in your combobox, but it wont bother you. will it? :-)
I got the following error:
There is no row at position 0
when I was setting ComboBox.SelectedItem to -1.
Replacing by ComboBox.ResetText() worked OK. This was using .Net 4.6.1, with VS 2013 where TextFormatting = True by default for ComboBoxes.
you may try to use this solution..
dataGrid.DataSource = Nothing
dataGrid.DataBind()
hope its help!..:D