I look for a way to observe a collection for changes, without using indices. I know when items are added and removed from the source collection, but the collection is not using indices (it's a custom kind of hashset with notification on add/remove). Items are being populated to the list in a undeterministic order and using indices wouldnt make much sense, so I'm trying to avoid it completely. But Im still going to bind this list to a view, so there will be some ordering of the items eventually. My goal is to have all the ordering in a collectionview.
The question is if there is a way to make a collectionview on a index-less source collection and still get the UI to respond to items being removed and added effectively without having to rebuild the list everytime. I'm not sure if I make any sense here. My goal is to get rid of indices but still benefit from collectionchanged-events and collectionview-ordering. Possible?
UPDATE
I've tried to implement a custom ICollectionView such as SetCollectionView(HashSet set) but it won't work for some reason. Not yet anyway.
Another option could perhaps be to implement a custom ReadOnlyObservableCollection-wrapper with some custom ordering on the GetEnumerator. I haven't tested it yet. I would have to sort the list according to the choosen ordering before extracting the index for the NotifyCollectionChanged-event but that should work.
You can use the ObservableHashSet class.
See the question here
How can I make an Observable Hashset in C#?
or go directly to the code here:
http://geoffcox.bellacode.com/2011/12/09/observablehashset/
You need to have an index somewhere, because all of the UI binding plumbing is index-based. You can layer an indexed list over your existing hashset, but it's going to be slow (I can't provide a formal proof, but my gut tells me it would be quite awful, something like O(n)). If you want a quick base collection that you can layer re-ordered UI lists on top of, you might want to look into a balanced sorted tree, rather than a hashset.
Related
I would like to get the same behavior as of List.Insert(Index, content )
In List , it just pushes the rest of elements forward while enables you to insert new element at specified index.
But I am dealing Concurrency so I can't use List anymore instead I need to use Concurrent collection. Any idea how we can achieve this?
Note :
I am trying to achieve custom Sorting of custom Objects stored in the concurrent collection( i.e. If at index = 2, Last Name is alphabetically less than the incoming LastName, it must allow the incoming to be placed at index = 2 , while pushing /sliding the old value to next indexes. Thus retaining all contents with new one)
The ConcurrentBag<T> does not provide the functionality that you are looking for. It's not a list, it's a bag. You can't control the order of its contents, and you can't even remove a specific item from this collection. All that you can do is to Add or Take an item.
The rich functionality that you are looking for is not offered by any concurrent collection. Your best bet is probably to use a normal List<T> protected with a lock. Just make sure that you never touch the List<T> outside of a protected region. Whether you need to Add, or Insert, or Remove, or enumerate, or read an item, or read the Count, or anything else, you must always do it inside a lock region that is locked with the same object.
As a side note, it is quite likely that what you are trying to do is fundamentally wrong. There is a reason that the functionality you are asking for is not available: It's practically impossible to use it in a meaningful way without introducing race-conditions. For example two threads could independently figure out that they must insert a new item in the index 5, based on the existing values in the list, and then both try to inserting it at this index, concurrently. Both will succeed, but one of the two items will end-up in the index 6 after being pushed by the other item, and the two items might not be in the correct order in respect to each other.
I'm working on a WPF application that utilizes ReactiveUI and DynamicData. Most of our lists are of the type IObservableList and at times we need to subscribe to changes on this list, and at times we need to simply iterate through the list. My concern is around if we're following the correct pattern for iterating through these lists.
Currently, when we need to iterate through a list, we follow the following pattern:
// Assuming we have an IObservableList<SomeObject> named objList with some data in it
foreach (var obj in objList.Items)
{
// some operation on obj
}
This pattern works fine, but we're concerned that this isn't a "Reactive" way to do this. Any suggestions?
Thank you!
Well, I'm not quite familiarized with IObservableList<T>, but I use Deferred Execution when working with IList<T>.
I would recommend to implement this when working with dynamic data, it will let you get the latest values whenever you need them.
check the link for more details.
You iterate through a list using a loop. Each of them works.
for is the obvious first candidate.
while works, but is a bit more writing.
foreach works - if you do not start changing the list. A quirk of foreach is that it only works with enumerators under the hood, and enumerators become invalid if the collection is changed.
One particulay thing to consider however is the "ElementAdded" Notification on (re)building the list. Usually they classes lack AddRange functions.
Unless you tell us what you do with SomeClass Instances during itteration and how the class looks, we can not tell you if it is "reactive" programming. But for me it feels like it is just a Buzzword.
I have a private List<Experience> experiences; that tracks generic experiences and experience specific information. I am using Json Serialize and Deserialize to save and load my list. When you start the application the List populates itself with the current saved information automatically and when a new experience is added to the list it saves the new list to file.
A concern that is popping into my head that I would like to get ahead of is, there is nothing that would stop the user from at any point doing something like experiences = new List<Experience>(); and then adding new experiences to it. Saving this would result in a loss of all previous data as right now the file is overwritten with each save. In an ideal world, this wouldn't happen, but I would like to figure out how to better structure my code to guard against it. Essentially I want to disallow removing items from the List or setting the list to a new list after the list has already been populated from load.
I have toyed with the idea of just appending the newest addition to the file, but I also want to cover the case where you change properties of an existing item in the List, and given that the list will never be all that large of a file, I thought overwriting would be the simplest approach as the cost isn't a concern.
Any help in figuring out the best approach is greatly appreciated.
Edit* Looked into the repository pattern https://www.infoworld.com/article/3107186/application-development/how-to-implement-the-repository-design-pattern-in-c.html and this seems like a potential approach.
I'm making an assumption that your user in this case is a code-level consumer of your API and that they'll be using the results inside the same memory stack, which is making you concerned about reference mutation.
In this situation, I'd return a copy of the list rather than the list itself on read-operations, and on writes allow only add and remove as maccettura recommends in the comments. You could keep the references to the items in the list intact if you want the consumer to be able to mutate them, but I'd think carefully about whether that's appropriate for your use case and consider instead requiring the consumer to call an update function (which could be the same as your add function a-la HTTP PUT).
Sometimes when you want to highlight that your collection should not be modified, exposing it as an IEnumerable except List may be enough, but in case you are writing some serious API, something like repository pattern seems to, be a good solution.
Let's say I have an IReactiveList<string> named Items from which I'd like to create some derived list DerivedItems (of type IReactiveList<string> or IReactiveDerivedList<string>) of distinct items only.
Items.CreateDerivedCollection(...) has all the bells and whistles I'd like to use, but it doesn't appear to have an option for filtering out duplicates.
I tried Items.Distinct().CreateDerivedCollection(...), but CreateDerivedCollection() no longer tracks changes when used with Distinct().
I tried Items.Changed.Throttle(...).Subscribe(_ => ResetImpl()) where ResetImpl clears DerivedItems and adds each item in Items one-by-one, but then I get exceptions stating that the enumeration cannot complete because the collection was modified. (This occurs primarily when I add dependencies on DerivedList.) I can add a lot of locks but this seems pretty messy.
Finally I tried manually triggering off Items.IsEmptyChanged.Where(b => b) and Items.ItemsAdded in an attempt to manually synchronize Items and DerivedItems, but here I run into a lot of timing issues where list clearing and item addition do not consistently happen in the right order.
I get the feeling I'm missing an easy solution to this problem. How do you do this?
I have a way of doing it, but it's not using IReactiveDerivedList:
var distinctElements = Items.Distinct().ToList();
Items.Changed.Subscribe(y =>
{
distinctElements = Items.Distinct().ToList();
});
I'm implementing my own BindingList<T> that supports sorting. Everything is working well so far, but I'm confused about how I should implement RemoveSortCore. The documentation is not very explicit, it only says:
Removes any sort applied with ApplySortCore if sorting is implemented in a derived class
Does that mean I should restore the original order of the items? The implementation shown in this MSDN article only sets _isSorted to false, without actually restoring the original order, which makes it quite useless IMHO...
If I want to be able to restore the original order, I guess I need to maintain a copy of the original collection (or is there a better way?). But if I do that, how do I handle modifications of the collection while it is sorted?
When overriding InsertItem, should I just add the new item at the end of the unsorted copy?
When overriding RemoveItem, I'm given the index in the sorted collection. But it means that if I want to also remove the item from the unsorted collection, I need to find its original position, which is an O(n) operation, while RemoveItem is normally expected to be an O(1) operation. The same question also applies to SetItem.
How would you handle that? Any suggestions are welcome
It is up to the implementer to define exactly what this means. The two most obvious choices are:
Revert the list to the original form: Official example here
Remove the Sort and proceed as if one had never been applied: As used in MS.SqlServer.Management.Controls.SortableBindingList