How to proceed related BindingSources when DataSource is empty - c#

I would like to ask for advice. I meet this model situation:
BindingSource headOfFamillyBS, its DataSources is List of objects List<FamillyResources>
This object FamillyResources have properties, among others, List<FreeTimeActivities>
Than I have two other BindingSources, one freeTimeActivitiesBS, which have DataSource and DisplayMember solved by DataBinding this way:
this.freeTimeActivitiesBS.DataBindings.Add("DataSource", headOfFamillyBS, "view_frTmActvts");
than
this.freeTimeActivitiesBS.DisplayMember = "view_shortName";
The problem is:
When I call on List<FamillyResources> method .Clear(), it has no items, moreover property view_frTmActvts (which return list) is of course empty (because no items in source list - in headOfFamillyBS). Than BindingSource freeTimeActivitiesBS goes throw exception:
DataBinding cannot find a row in the list that is suitable for all
bindings.
Is there any elegant way, how to handle situation, that LIST properties of top BindingSource, which other BindingSource has as theirs DataSource, is null?
Should I manual handle ListChanged event of headOfFamillyBS and check if List is empty, than Clear bindings to all other connected BindigSources? This will be pretty slow in case of houndreds or thousands items in source list.
Thanks for any advices!

Related

ComboBox Items Empty but DataSource Full

After binding a list to combobox, its dataSource.Count is 5 but, combobox item count is 0.
how can it be?
I'm used to Web programming and this is in Windows Forms.
So no combo.DataBind(); method exists.
The problem here is, I'm trying to set the selected item programmatically. Since I don't see the combo.Items collection filled, I cannot set the desired item.
Update
A total update is needed I guess:
datasource contains 7 items
when bound to combobox, DisplayMember and ValueMember are appropriately implemented
after databound, through the gui, I can clearly see the 7 items in the combobox
combobox.DataSource.Count = 7 and combobox.Items.Count = 0
So the problem is here; since after databound no items are there in the ItemCollection of combobox; I cannot search for one to match and set the appropriate one.
Here is a image for better understanding (But I'm pretty sure I'm missing sth simple)
After adding ddl.BindingContext = new BindingContext(); before the BindingSource assignment, everything worked fine.
If you'd expand DataSource items in debuger, you'd probably notice that 1st element on list is null. That is why DataSource does not render ComboBox Items. Removing null items from the list should do all the work;
I had the same problem, but in my case it was caused by calling
combobox.Sorted = True
in InitializeComponent. I guess that call initializes Items, which then prevents the assignment to DataSource from updating it (Items).

How to bind DataGridView to SubList

I have a Singleton BindingList list with objects.
I need to bind this list to DataGridView.
I need the grid to show only objects with specific property value (Property IsEmpty and I want to show only objects with IsEmpty=false).
I tried to iterate trough the DataGridView rows after the bind completed and hide rows with IsEmpty=false. This worked but the grid doesn't work well in some situation like sorting of columns.
My conclusion is I need to have a sublist of the original list with refrence to all the objects in the original list that have property IsEmpty=true.
Any idea what is the best way for doing this? (I need to preserve the ListChanged event in the new list for the binding work well)
You'll need to filter your data source before binding to your grid. The best way would like be with a call to linq's Where method.
IEnumerable<yourType> initialSource = getYourSource();
yourGrid.DataSource = initialSource.Where(x => !x.IsEmpty).ToList();
This will keep your original collection intact, and will bind the grid only to those objects that match the filter.
Edit
If you can't use linq, then why not a simple loop?
List<yourType> filteredSource = new List<yourType>();
foreach(var item in initialSource)
if (!item.isEmpty)
filteredSource.Add(item);
yourGrid.DataSource = filteredSource;

DataGridView not updating when additional rows are added to the bound DataSource unless I null it out first

I have a winForms DataGridView bound to a List<MyObjectType>. My problem is that once I do the initial myDataGridView.DataSource = myObjectList; that adding/removing elements from the list is not reflected in the displayed DataGridView even though in the debugger the row count on myDataGridView.DataSource does update.
I'm able to force the DGV to update the displayed rows if I null the datasource before reassigning the list to it. This looks ugly though and I'm wondering if I didn't miss an easier way to do this.
myDataGridView.DataSource = null;
myDataGridView.DataSource = myObjectList;
The List<T> collection does not support change notifications, so the DataGridView will never be able to detect when you add/remove elements. Consider using ObservableCollection<T>, which does support change notifications.

wpf binding in c# to a filtered list

I have recently begun development using c# and wpf. In our application we have a DataGrid object that we would like to bind to a list. However we do not want all entrys in the list to be bound, only those that meet a certain criteria. The reason that we cannot bind to a seperate list (ie. bind to a list created by the applying the filter) is that we would like 2 way binding, so that when a user adds a row to the table it will be added to the overall list.
Question1: is it possible to bind to a 'filtered' list
Question2: if not what is the best way to get this functionality? i.e. display only certain values but add all new entries to the overall list
thanks in advance
sam
What you want can be accomplised using the CollectionView classes. Here is how to create one with a DataTable as the source.
DataView myView = new DataView( MyDataTable );
ICollectionView cv = CollectionViewSource.GetDefaultView(myView);
You can also use ObservableCollection for a collection of your custom classes. After you create your collection view, you can set filters and sorting and grouping. In the UI, you bind to the CollectionView and you are good to go. So, for multiple views of the same data, just create different CollectionView instances and bind to those. When you update a value on the UI, the item in your store will update "automatically"
this site contains a pretty decent, but simple, example

How to remove selected items from ListBox when a DataSource is assigned to it in C#?

How to remove selected items from ListBox when a datasource is assigned to it in C#?
When trying to remove, got error
"Items collection cannot be modified when the DataSource property is set."
But when i try to remove item from datasource (datatable) ,
it thorws error as "datarow is not in current row collection".
Find that item in the DataSource object and remove it, then re-bind the ListBox.
EDIT:
Here's how you delete from a DataTable as your DataSource, regardless of the .NET version.
DataRowView rowView = listBox.SelectedItem as DataRowView;
if (null == rowView)
{
return;
}
dt.Rows.Remove(rowView.Row);
I haven't tried with anything other than WinForms DataGridViews, but I highly recommend BindingListView, which is both faster than DataTables/Views and allows you to bind generic List<T>s as your DataSource.
Alternatively, use a list that implements IBindingList or inherits from BindingList. When objects are added or removed from a Binding List, any controls bound to it are automatically notified of the change and will update themselves accordingly. If you are using BindingList and your class also implements INotifyProperty changed, Any changes to class properties will also be updated automatically in the databinding control. For example, if a column in a datagrid(view) is bound to a property, "Name", and you change "Name" in the datasource, the datagrid will automatically update. If you add a new item to the datasource, the datagrid will update automatically. Binding List also supports notification in the other direction. If a user edits the "Name" field ina datagrid, the bound object will be updated automatically. Going off topic slightly, if you go a little further and impliment "SupportsSortingCore" and the associated methods in BindingList, you can add automatic sorting to your data. Clicking on a columnm header will automatically sort the list and display the header sort direction arrow.
If the ListBox has a datasource assigned, you must remove items from the datasource and then rebind the ListBox
You need to modify the data source rather than the Items collection of the control. Depending on what kind of data source you are binding to, there are going to be different things you have to do so that your UI updates.
The best way is find a collection that fits your needs and implements IBindingList or IBindingListView. Those two interfaces implement even handlers that listen for a CollectionChanged event and update your UI accordingly.
If your collection doesn't support those interfaces, you're going to have to re-bind your data source every time somebody adds/removes an item.
when you get the message "Items collection cannot be modified when the DataSource property is set."
setting the datasource to something else, empty list or null does not help when
the code initializecomponent is not completed.
to avoid that error, one must do the change of datasource or the item list during or after form load.
I know it does not seem to make sense. Hoever, the visual studio designer will generate code in the form designer.cs or vb that will add items to the listbox if any code that changes the items is found before end of initialize components
While Chris Doggett posted a valid solution, I ran into problems while using it. By using that method it was not allowing a subsequent GetChanges(DataRowState.Deleted) to work properly.
To better solve my problem, I only had to change a single line - the last line.
DataRowView rowView = listBox.SelectedItem as DataRowView;
if (null == rowView)
{
return;
}
rowView.Row.Delete();
This allowed my GetChanges call to work properly.
This worked for me
DataTable temp = (DataTable)lstBlocks.DataSource;
temp.Rows.RemoveAt(position);
its vary simple , assign a new blank value to listbox
eg..
Dim ABC As New List(Of String)()
ListBox1.DataSource = ABC
ListBox implementation is bugged, you need to create a new data source instance for the component for it to recognize a change.
Eg:
ActivitiesList.DataSource = _activities;
_activities = new List<Activity>(_activities);
_activities.Remove((Activity)ActivitiesList.SelectedItem);
ActivitiesList.DataSource = _activities;

Categories