I have a ListView and it's getting updated every 5 seconds.
The problem is that the selected item vanish. How can I obtain it ?
It depends what you're doing to update the list. If you're deleting and re-building the list willy-nilly (which isn't great), you'll need to store something which can uniquely identify the selected item before deleting the list and then use that stored value to select it again once the list is repopulated. A better solution is to use something like an ObservableCollection, and try not to wipe out anything in the list unless you really need to.
Related
I use EditItem/CommitEdit for resorting (grouped) collection when some property of any item has changed. I do not want to call Refresh() because the collection contains a lot of items with relatively complicated visual tree so it slows down the application.
I faced some strange behavior when calling CommitEdit for current (selected) item - it will lost its currency during the process, of course I can still set it back through MoveCurrentTo(item) so everything looks fine at the moment. But... When for example a new item is added to the collection, the current item will automatically change with no reason to an item on the same index as was the edited item before the collection changed (added item) - it does not normally happen without calling CommitEdit in past.
I use master/detail model so properly set current item is very important for me. Did anyone went around it?
So I was digging around it, debugging ListCollectionView and found there a bug (in my opinion). When a CommitEdit is called for any item, the item needs to be removed from collection and again added into it so the item can lost its currency during the process - thats expected. But there is a special case when edit a current item, some private field called _currentElementWasRemoved is set to true. When the collection will change next time (add, remove...) it looks into this field and change the current item, but in that time the current item should have already changed (I can call f.e MoveCurrentTo multiple times meantime) so this behavior is completely useless in my eyes.
So the walk around can be following: before calling the Edit/Commit for current item, move current pointer into another item or "deselect all" via MoveCurrentTo(null). Right after the CommitEdit was called you can simply return the pointer to the origin item by calling MoveCurrentTo(item).
I have a listview that contains a list of 'rows', which in term, contains a list of 'columns'. For now, I use List for both rows and columns (i.e. I have a List and it the Rows objet, I have a List, but as the number gets bigger, the time it takes to update the GUI and overall performance of the program gets pretty bad. Plus, the GUI isn't notified when the items (columns within the rows) change, so I have to do an Item.Refresh, which seems to refresh the whole thing each time, adding to the slow performance
Is there any other type of object that I could use to accelerate the whole thing. Meaning it would need to satisfied the following points :
- Faster that List
- When I add a new rows, the listview is updated. Is possible, only the new rows is added instead of the whole listview.
- When I change a Columns object, the GUI is updated. If possible, only the modified columns objet is affected so the whole Listview is not changed.
Note that there are quite a number of actual calculations behind the scene for displaying the columns object. I have currently working on optimizing this end, but I'm pretty sure using a better collection would help quite a lot here.
Thanks
I believe what you are looking for is an Observable Collection
This collection type will fire a CollectionChanged event when items are added. You will not need to refresh the collection because WPF controls support this out of the box.
Note
The CollectionChanged event will not be fired when indiviual elements are updated. If you want these updates to show on the UI, the object within the collection should implement INotifyPropertyChanged
I want to filter out a single item in my CollectionViewSource
I already have other filters applied, but I'm trying to find a way of filtering out an individual item without having to call a function that iterates through all items.
Is this possible?
It's not exactly clear what you're asking, or what your concern is. Perhaps if you elaborate I could give a better answer.
However, as I see it, you have these options:
Don't include the item in the underlying collection (or have a separate collection that does not contain it) and base your collection view on that
Adjust your existing filter so that it excludes the object in question
Create another collection view over your existing collection view that filters out the item
If the item is in the underlying collection, how else could you reasonably exclude it but via the filter?
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