I use a
SynchronizedCollection<SomeClass> to synchronize a list between some threads. This works great, but now I would like to populate a text control always with the latest item added to the list.
It seems that this list is not observable so it does not have a Changed event. Any advice on how to accomplish this?
Related
I have some kind of file explorer using a ListView to show the files. When i open a folder containing a few thousands of files, the UI hangs around 5 seconds while the ListView is refreshing.
Is there any way to avoid that ?
Thanks
Virtualisation is a must for large collections like these. Without it, WPF will have to create a visual tree for EACH item in your list ahead of time.
Just a hunch, but are you using an ObservableCollection to bind the collection of files to the ListBox?
I've had performance problems with large collections and the ObservableCollection. You can only add/remove items on the UI thread - if you're iterating through your file results, and adding them to the observable collection then you're going to experience this kind of lag.
Best solution in that case is to compile your file list as a separate list, and create a new ObservableCollection, passing the list in through the constructor. This minimizes the hit on the UI thread.
Add the items to your ListView's datasource with DispatcherPriority set to Background.
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => AddNewITemToList(newItem));
The performance problem you have now is related to a fact that control creates UI elements for all thousand of files found, even if renders only small amount of them.
You need at least use ListView.VirtualMode to implement kind of paging in your control.
In practise what happens is that in this mode, the control's ListViewItem is created dynamicaly , so you can use ItemsCollection of it, but you can control the creation of every single item required by UI in single moment, so improve performance too.
There is also an option of Data Virtualization, where the data bound to your control is virtualized too, and not only UI of the control.
With a list view containing items I can reorder which gives a nice UI effect.
I have my item source for the list view hooked up to an observable collection. Is there anyway with the framework I could programatically simulate a reorder and give the same effect you would have if you actually reordering?
The only way I've been able to slightly achieve this is to literally clear all the items from my data source then repopulate after shuffling the items, however it doesn't look nice.
Well, you could sort the items in code-behind in a temporary helper array and then according to the order they are in in the sorted one start periodically moving items one-by-one in a small time interval (with DispatcherTimer) withing the collection - remove at it's index and insert somewhere it belongs. I think there is no built-in way to do it in a simpler manner.
The title of the question is bad, feel free to update it.
I have an observablecollection that generates a user control whenever it an item has been added to it.
However there are times where I just want to add to the collection and not have it create a usercontrol. Is there a way around this problem? Thanks.
Create a collection view around the observable collection and bind the UI to that. The collection view will have a filter so that only items you want in the UI are filtered in
I am experimenting with WPF and MVVM in our system. However iam having a problem with keeping things selected in lists using only MVVM ( without doing extra CollectionViews ).
What i currently have is the list
ObservableCollection<ReservationCustomerList> Customers;
And then a property storing the selected Customer
ReservationCustomerList SelectedCustomer;
In my opinion now, when the list reloads (actually from another thread async), the selection should be able to be kept, however this does not happen.
Does someone have a nice clean way of achieving this ?
The way we did it was that we did not replace the collection. We added/removed the entries and updated existing entries if required. This maintains the selection.
You can use LINQ methods like Except to identify items that are new or removed.
In case the reloaded list still contains the last selected item and you want that item to be selected, then you can raise the PropertyChange event for the property SelectedCustomer after your collection gets reloaded.
Please make your sure your viewmodel class implements INotifyPropertyChanged interface.
you can use the ICollectionView to select the entity you want.
ICollectionview view = (ICollectionView)CollectionViewSource.GetDefaultView(this.Customers);
view.MoveCurrentTo(SelectedCustomer);
in your Xaml the itemsControl must have IsSynchronizedWithCurrentItem=true
or if the ItemsControl has a SelectedItem property you can simply bind it to your SelectedCustomer Property.
When you "reload" your collection you basically replace all values in it with new values. Even those that look and feel identical are in fact new items. So how do you want to reference the same item in the list when it is gone? You could certainly use a hack where you determine the item that was selected by its properties and reselect it (i.e. do a LINQ search through the list and return the ID of the matching item, then reselect it). But that would certainly not be using best practices.
You should really only update your collection, that is remove invalid entried and add new entries. If you have a view connected to your collection all the sorting and selecting and whatnot will be done automagically behind the scenes again.
Edit:
var tmp = this.listBox1.SelectedValue;
this._customers.Clear();
this._customers.Add(item1); this._customers.Add(item2);
this._customers.Add(item3); this._customers.Add(item4);
this.listBox1.SelectedValue = tmp;
in the method that does the reset/clear works for me. I.e. that is the code I put into the event handling method called when pressing the refresh button in my sample app. That way you dont even need to keep references to the customer objects as long as you make sure that whatever your ID is is consistent. Other things I have tried, like overwriting the collections ´ClearItems()´ method and overwriting ´Equals()´ and ´GetHashCode()´ didn't work - as I expected.
C#: What is the best way to implement a 'filter' mechanism for ListView Items?
I want to filter out some listview items from view in 'details' mode where it contains rows and columns. What would be the best option to create such a mechanism where I could rapidly remove the items in question from view, leaving the others intact, and putting them back into the listview when there is no more need to filter out listview items? Should I remove/copy them to a List and just and add them back when done or would there be a better method of doing this more effeciently? The listview will be handeling about 100-500 items.
If you are working with a databound control you will have this facility within the binding framework.
If not, I would probably store all the items for the list separately and populate the control in full each time, based on any contextual requirements such as filtering. The code to iterate through the list and move items not required at present is probably unnecessarily complicated. A full repopulate each time will be easier and won't differ much in terms of computational expense.
This behavior is built in to BindingSources using DataSets in .Net 2.0.
For .Net 3.0+, you can use LINQ.