I have source elements like this:
var collection = new ObservableCollection<SourceItems>(source);
source implements INotifyPropertyChanged
I need to edit and view this collection in CheckListBoxes (listBox with checkBoxes from WPFToolKit)with rules:
every CheckListBoxes must be sort by one of collection's field. Collection has order field for each CheckListBox. For example - ItemOrder.
visible elements in one listBox depend on checked items from other.
Every CheckListBox has itemsSource
checkListBox1.ItemsSource=collection;
So, if i check items in one listBox i must see only checked items in other.
And every listBox must be sorted by one of source's field
listBox1 by field orderItem
listBox2 by field orderVisibleItem and so on.
User can move elements in each listBoxes and it must not affect ordering in other.
I tried create CollectionViewSource for every ListBox. But when I sort one, it sort each other.
Linq for filtering and sortnig don't work too, because changes not updating dynamicly.
Is there best way to create such functionality?
You should use CollectionViewSource.
I'm guessing that you used CollectionViewSource.GetDefaultView(.. ) ? you should create two NEW views for the collection:
CollectionViewSource cvs = new CollectionViewSource() { Source = TheCollection };
Related
I have created a custom control that displays a composite collection on a grid panel. It looks something like this:
The 'slots' behind are a uniform 1 row apart and span 1 row each. The 'items' on top can be created at any row and can span multiple rows.
I would like to implement the functionality of SelectedItems from the Selector class on the first collection of 'slots'.
Can I derive from Selector (e.g., a listbox) and still create something like the second collection overlayed over the first?
Don't use a composite collection. Create a base class or interface and make a single collection of that type. Then extend that class or implement that interface in each of your various different objects that you want to display. Now you'll be able to add each of them into your single collection and just use a normal ListBox with SelectionMode = SelectionMode.Extended or SelectionMode = SelectionMode.Multiple.
I have a custom panel control that is intended to be used as an itemspaneltemplate in a items control.
The itemscontrol will be databound to a data source.
This datasource is a List, and each item in the list is a custom business object.
In the application, the user is able to update each of these business objects in the list, and that fires the notification on property changed as expected.
Now my problem is here:
When the user updates the object's properties in the data source (the itms in the List) that the items control is bound to, my custom panel control is not able to get that notification, so as a result the items control does not get updated with the updated items in its view.
I tried using an ObservableCollection instead of List - the problem is still the same.
I must be missing something fundamental here... please help with any pointers, answers or solution.
Change notification in a collection is a bit tricky. Say you have a collection of Products. you can implement change notification is three different places.
Change notification in the Product class (implementing INotifyPropertyChanged in class Product)
Change notification in the collection itself (i.e. using ObservableCollection)
Change notification in the class that holds the collection, that is, implementing INotifyPropertyChanged on the class that contains the collection. (usually this would be the ViewModel under MVVM)
Those tree ways are not the same, and each is for a different situation.
Let's say that the collection is ObservableCollection<Product> Products {get;set;}
if you want changes in the product to register (i.e., if you're doing something like Products[0].Name = "New Product"; then #1 is the right one.
If you want to do Products.Add(new Product(...)) then #2 is the right one.
If you want to do Products = new ObservableCollection<Product>() then #3 is the correct one. This is especially tricky since i'm not changing the collection, but creating a new one, so the ObservableCollection won't help - I'd need to implement INPC in the containing class.
I have a DataGridView control that is bound to a custom typed list (that inherits BindingList). I would like to be able to filter rows based on a simple column value (bool type). Ultimately, the fonctional goal is to be able to mark an item as deleted but just flag it as deleted in the DataSource, not remove it. Juste remove it from the grid, not the DataSource.
Any idea ?
You can use LINQ to filter your data then create a new BindingList and reassign it to the dataGridView.
Assuming you have a flag in the person class called WillBeDeleted:
dataGridView1.DataSource = new SortableBindingList<Person>
(SampleData.Where(p => !p.WillBeDeleted).ToList());
Good luck!
Just to make it clearer, I used this code to create the SortableBindingList http://www.timvw.be/presenting-the-sortablebindinglistt-take-two/ (I translated it to VB.NET)
Then, I have my own collection object that contains properties and a SortableBindingList of my entities.
Private mListeNotes As New SP1ZSortableBindingList(Of SP5004ZNoteEvolutiveEntite)
And that is what I bind my grid to so I it is now sortable. So I need it to remain of that type, not generic list.
I appologize for the novel but I wanted to explain as much as I have done thus far.
Within my current project I have an application that consumes a service that provides a collection as a <List>. Due to how I am using this data in the application I have had to convert this data to an observable collection. This was done so that as the data was selected and moved about the application UI updates would be refreshed using INotifyPropertyChanged and INotifyCollectionChanged.
Where I am having a challenge now is I have a listbox that is bound to the observable collection within the listbox I have a datatemplate that renders out the items of the collection. This data template contains a button which needs to allow the user to click the button for each item to remove them from the collection.
The use case for this is a listbox that stores selected name as chosen from a gridview. Once the user has selected names from the gridview they are stored ( within the observable collection as a queue) and rendered out in the UI in a listbox control which shows all selected names. I need to provide the user with the ability to remove these names in any order selected.
From what I have been reading there is no means to enumerate / index an observable collection. For situations such as this you should use List or an Array. However in order for the items to refresh in the list view they need to be in an Observable Collection.
From what I have read it appears that when the event is triggered I need to convert the observable collection to an Array and then evaluate the array to determine the index and then remove the record accordingly?
I think I may be off base on this as it seems like I am over engineering this problem? The above scenario does not seem correct is because I fell as if I am doing a lot of converting to and from the collections to just remove a record?
Does anyone know of an efficient means to remove records from a collection ( in any order selected) when the collection is rendered out as an items control within a listbox?
I’ve been successful in removing the last record added to the collection using RemoveAt() however I have not had any success in randomly removing records.
Afterthought: Part of this issue could be related to the fact that I have a button inserted within the datatemplate (control item) and as a result the item is not actually being selected before the event is fired on the button event?
Sorry for the rambling on this but I have had my head in this for hours and made minor progress. Any tips or ideas would be appreciated!
ObservableCollection<T> inherits from Collection<T> which implements IList<T>, so you can certainly index and enumerate it. It has a Remove method that takes the object to remove and removes the first occurrence in the collection and a RemoveAt method that takes an index and removes the item at that index.
Based on your afterthought, it sounds like you have a WPF ListBox with an ItemTemplate that creates a Button. ListBox will set the DataContext of each instantiated template to the item in the list being bound to, so you can get a reference to the item that created a Button from the DataContext property on the Button or by using a Binding.
I am working on an MVVM-based WPF app that uses the DataGrid. The grid is data-bound to an ObservableCollection<Widget> (the Widget list). The user needs to be able to insert a Widget into the list below the currently-selected Widget, to delete a selected Widget, and to reorder the Widgets on the grid. I'll implement the reordering through dragging and dropping.
Before I dig into this, I want to get a reality check on my approach. Here is what I am planning to do: The Widget class will have an Index property that will be used to order the Widget list. Additions, deletions, and reordering will be done by manipulating this Index property, and sorting will be done on the Widget list, rather than through a CollectionView.
Before the DataContext is set, the Widget list will be sorted on the Index property. When a user adds a Widget, the Index property will be incremented by 1 for each Widget below the selected item on the grid, and the new Widget will be given the index number opened up by the renumbering. The Widget list will resorted, and the bindings will be refreshed.
When a user deletes a Widget, the Widget will be removed from the list, and the Index property of items on the grid below the deleted item will be decremented by 1. The Widget list will be resorted, and the bindings refreshed, as above. Reordering will be done as a combination delete-and-insert.
Here is my question: Is this a reasonable strategy for implementing inserting, deleting, and reordering? Is there a better way to go about it? Any good articles or blog posts on the subject? I've looked, but I'm not coming up with anything on-point.
Thanks for your help.
I've got this problem figured out. I do need the Index property, but I don't need to sort the ObservableCollection. I create an interface, IIndexedObject, with one property, Index. I implement that interface on any object that needs to be indexed, and in my database table, I add an Index column.
When I load into my object model, I sort the database table on the Index property. That ensures that the list is loaded in the same order as in the last run. I add objects using the blank row provided at the bottom of the DataGrid. It gives them an index of 0. I delete objects using a Delete button bound to an ICommand in the view model.
My view model subscribes to the CollectionChanged property of any ObservableCollection that contains IIndexedObjects. When the event fires, the view model passes the collection to a ReIndexCollection service method, which takes an IIndexedObject. The method re-indexes the collection, based on its current order, by simply iterating the collection, assigning an incremental integer value to each element's Index property. When I persist the collection back to the database, the Index value gets saved, to ensure that the collection is loaded in the same order on the next run.
Since the only sorting that is needed is done at the database load, there is no need to sort the ObservableCollection. When I move items on the DataGrid, it will take care of re-ordering the collection at that time. All I have to do is re-index the collection, so that its order will be persisted back to the database.
All-in-all, it's much easier than I had expected. One of the reasons I like WPF and MVVM.
Improving sorting performance:
http://blogs.msdn.com/jgoldb/archive/2008/10/30/improving-microsoft-datagrid-sorting-performance-part-3.aspx