I'm working on a project that controls multiple devices over USB and intercepts the WM_DEVICECHANGE events from Windows to manage currently connected devices and plugin modules using those devices. There exists a combobox on the main form that (should) display all available devices (the custom object) and be dynamically updated in the event of either device arrival or removal.
Now, every tutorial that I have read including some from here have directed me to set the DataSource property of the combobox to the List of objects that I have, and leave the DisplayMember/ValueMember property blank to display ToString() and to return the object as the value.
In some instances I have tried (such as post instantiating the List and populating it with sample/real objects) the combobox populates, however upon removal or arrival, the collection in the combobox does not update even when reassigning the List to the combobox's DataSource property after every device arrival/removal method.
EDIT: Oh right... the question...
How do I databind the collection of (custom objects returned as the values) dynamically such that it can handle sudden changes (additions/removals) to the list's contents?
EDIT 2: Sorry I didn't make this more clear, wasn't aware of how pervasive WPF has gotten, but this is a WinForms project.
Thanks in advance for any help you can provide. :)
even when reassigning the List to the
combobox's DataSource property after
every device arrival/removal method.
After reassigning, you need to call .DataBind() again.
If you're using .net 3.5 or above, you can use an ObservableCollection to have the list update automagically.
I'm not sure if you're using WinForms or WPF. I'm assuming WPF as nobody should start out on WinForms nowadays...
You need to change your List to an ObservableCollection<T>.
The WPF binding model relies heavily on a magic subsystem of fairies and warlocks (not mocking you, I'm actually serious). They have their own language for informing each other that something has changed between the DataContext and UI. These are primarily the DependencyObject/Dependency properties, INotifyPropertyChanged and INotifyCollectionChanged, and the ObservableCollection<T>.
By proper use of these totems, changes in your ViewModels/Models (the stuff you stick in the DataContext and/or bind to the DataSource) will be reflected on the UI.
I don't know about that ToString() bit. I always set the DisplayMember to the Property I want to display. I don't care about the ValueMember because the SelectedItem is my Object.
DataBind doesn't apply if this is a WinForms project, which it sounds like. (USB and stuff)
I don't do anything funky in my project when up update the data in a ComboBox, I just set the DataSource again.
EDIT:
You could try using a BindingList rather than a List also.
http://msdn.microsoft.com/en-us/library/ms132679.aspx
Related
I'm currently working on a WinForms graphical interface in C#. The form has a ComboBox that is displaying the contents of a custom class I wrote. This class implements the IList interface so that it can be used as the DataSource for that ComboBox.
The issue is that when I add or remove items to/from the underlying object, the ComboBox does not visually reflect this.
I have tried reassigning the list to the DataSource property whenever the contents change, but that doesn't seem to make a difference.
Most of the answers on this site that deal with this issue or similar seem to require a number of extra classes, or editing XAML documents, in order to achieve this.
Is there a simpler method to achieving this? If it makes a difference, the ComboBox will not be visible at the point where changes are made to the IList sourcing it. The only idea I've had so far is to possibly delete the ComboBox and replace it with a new one when needed, but I'm not sure if this is possible to do at runtime, and is obviously not very elegant either way.
I have a C# Windows Phone 7.1 project that uses the MVVM Light toolkit. On one application page in the app I have a Telerik data bound list box that is bound to a property in my view model. At first that property had a return type of:
List<string>
With that return type the property did not show up in the list of candidate elements in the Path list box, when I activated the Create Data Binding dialog box in order to assign the list box's ItemsSource property. However, when I changed that property's return type to:
ObservableCollection<string>
it showed up immediately. In the future, how can I determine the correct return type for a particular control's ItemsSource or other data bindable property?
Your question is little confusing. Both are completely okay and work well for different scenarios. You use list<string> when you don't plan to change collection, and ObservableCollection otherwise.
Now, you can use MSDN(see ItemsSource property to see what property needs to be what.
As you can see from documentation, ItemsSorce has to be IEnumerable, meaning all types that derive from it, can be used.
Now as for the real question, why didn't your property show up in the IDE, I can only guess that Microsoft wants you to use ObservableCollection always, but I don't agree with this. So that's why it's best to manually do the bindings to properties through Xaml.
I'm currently building an application that utilizes a ComboBox to allow the user to select from a dynamic list of String objects contained within a BindingList object. However, the BindingList is a member of a child class belonging to the main class, which appears to be causing some issues.
When the ComboBox's data source is set initially within the main class via:
this.comboBox.DataSource = this.childClass.dataList;
the contents of the ComboBox appear as expected. However, when the contents of the list changes, the contents of the ComboBox are not updated.
If the BindingList object belongs to the main class, the ComboBox updates without any issues. It would appear that the parent class is not receiving the events that signal that the list has been updated.
Any ideas?
After looking at a similar question I asked (and answered) last year:
Adding/Removing COM Ports from a ComboBox in C#
, it seems I've (re)discovered the solution. The problem was with how the strings were being added to the data source. Because the list was being augmented in another thread, there was an issue with the ComboBox control being updated. By utilizing a delegate and the Invoke() method, the contents of the ComboBox are now updated as expected.
I am trying to create a program (simple grid - with specialized output) that displays data from an IBindingList data source. I can display the data just fine, but I also want to be able to let the user edit the data in, say in a TextBox that is separate from the grid. My problem is that I am unclear as to how to accomplish the "automatic" updating of the data between the two elements (my grid and the editable textbox).
The list's ListChanged event, I believe, will tell me when the list itself has changed, but I need the grid to know when the actual data in the list has changed. The only thing I have stumbled upon to tell me when a change external to the grid has occurred is to hook onto the BindingManagerBase.Bindings[0].Parse event. Not that a user would do this, but if the user has established several textboxes that are all bound to the same field, I think I would have to loop through each BindingManagerBase.Binding entry and hook it?
I am presuming I am not doing this correctly, and there is a more generalized way to accomplish this. I would GREATLY appreciate some direction from anyone who is more familiar with what I am attempting to accomplish.
Thanks in advance,
-Matt
Have a look at at INotifyPropertyChanged. Implement it on the class that is stored in your BindingList to notify said BindingList when properties on an item change.
If you've implemented IBindingList yourself you'll need to do a little more work to hook up to the events for each item in your list, but the provided BindingList will pick up on these events automatically.
You could also use the generic BindingList and notify the edit using ResetItem
For some reason when adding or remove items from the DataSource (a simple BindingList) the ComboBox updates accordingly but if I edit an item like this, it doesn't update automatically:
myBindingList[index].Name = "NewName";
myBindingList[index].Value = newValue;
In order to get it to update when I edit an item as opposed to creating or removing an item I have to do this after the change is made:
myComboBox.DataSource = null;
myComboBox.DataSource = myBindingList;
This fixes the problem but it seems like a rather messy solution. Also with large lists it may become slow (premature optimization I know) but still is there a way to force the ComboBox to update without completely re-assigning its DataSource?
Thanks for reading.
this is stated in the MSDN forums:
The IBindingList interface contains the ListChanged event where
controls like the combobox hook up into if the underlying datasource
assigned to it implements the said interface. your datasource must
raise the corresponding ListChanged with proper ListChangeEventArgs if
ever you add, remove, change, etc. your IBindingList implementor.
this way, whenever the underlying source you used to bind to your
combobox is changed, the corresponding UI control (combobox) is
refreshed.
you say you are using BindingList and in fact you do get the combobox to reflect add or remove items events. I think you should do the update of the items already inside your BindingList in another way because looks like the proper BindingList events are not firing.
you could either investigate into that or simply live with reset and reassign the DataSource, I don't think is too bad, you are in Statefull Windows Forms application not in SatetLess Webforms so you do have your objects there all the time :)
You need observable collections and IPropertyChange implementation:
ComboBox bound to a ObservableCollection does not update