Giter Club home page Giter Club logo

observablecollections's People

Contributors

github-actions[bot] avatar guitarrapc avatar hadashia avatar kawaisky avatar neuecc avatar nevermorewd avatar proudust avatar prozolic avatar torisoup avatar yenmoc avatar yossiepon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

observablecollections's Issues

A zipped sequence causes an exception in ObservableList.AddRange.

I am getting an exception with the code below.

using ObservableCollections;

var seq1 = Enumerable.Range(0, 1);
var seq2 = Enumerable.Range(0, 1);
var zippedSeq = seq1.Zip(seq2, (num1, num2) => (num1, num2));

var list = new ObservableList<(int,int)>();
list.AddRange(zippedSeq); // IndexOutOfRangeException raised.

I think there's something wrong with the CloneCollection construction process when the enumerator doesn't support NonEnumeratedCount.

CloneCollection.TryEnsureCapacity seems to be returning an empty array.

Requests when used in combination with R3

I have two requests.

1. readonly-observable-Dictionary

The IReadonlyReactiveDictionary that existed in UniRx was easy to use, so we request a function equivalent to it.
If I tried to handle the current ObservableDictionary Readonly, I would have to divide it into two parts, IReadonlyDictionary and IObservableCollection<KeyValuePair>, which is not easy to handle.

2. Publish OnCompleteMessage from IObservableCollection.

When dealing with IObservableCollection in R3, I feel uncomfortable that it is not possible to unsubscribe from the collection side.
For example, could it be possible to make IObservableCollection inherit IDisposable and issue OnCompleted on Dispose()?

Running filter for initial elements

Hi,

because filter is attached to the view after creation it is not run for the elements that already in the collection when the view is being created. This breaks Unity example that sets parent in the filer Add event.

What is the correct solution?

  1. Add the same logic as in the filter Add in the CreateView() factory? (setting parent on creation)
  2. Is there a way to run filter on creation?

ObservableList.AddRange(IEnumerable) adds nulls due to a bug in CloneCollection

I discovered this while using ObvervableList.AddRange(IEnumerable<T> items), which uses CloneCollection to turn the IEnumerable into a known-length collection as efficiently as possible.

In CloneCollection there is a bug inside the filling loop when it calls TryEnsureCapacity(ref array, i) on the array being filled.

Here TryEnsureCapacity() allocates a larger array without copying the old array items into the new one. As a result, the previous array contents are lost and are null in the final result.

Workaround: it works if I call ToArray() on my IEnumerable so that it will call ObservableList.AddRange(T[] items) instead.

Best way to add to Unity project?

In the Getting Started section of the README it says to read the Unity section, but the section does not mention how to install. I do not believe it's possible to install it through nuget in the package manager, and there isn't a upm branch.

Are we meant to clone the repo and extract the Unity code into a project as a local package, or is there a way to add the package via Package Manager?

Apologies if this is a silly question! Thanks for making something a slick package - I just want to make sure I'm using it correctly :)

Unable to Cast ObservableList<Class> to IObservableCollection<IReadOnlyClass>

I am currently facing a type conversion issue where I am unable to cast ObservableList<Class> to IObservableCollection<IReadOnlyClass>. Below is the relevant code snippet that demonstrates the issue:

using ObservableCollections;

public interface IReadOnlyClass
{
    int Value { get; }
}

public class Class : IReadOnlyClass
{
    public int Value { get; set; }
}

public interface IReadOnlyExample
{
    IObservableCollection<IReadOnlyClass> List { get; }
}

public class Example : IReadOnlyExample
{
    private ObservableList<Class> _list;

    // CS0029: Cannot implicitly convert type 'ObservableList<Class>' to 'IObservableCollection<IReadOnlyClass>'
    public IObservableCollection<IReadOnlyClass> List => _list;
}

I am looking for a solution or workaround that would allow this type of conversion, ideally without having to manually create a new collection or extensively modify the existing data structures. Any suggestions or insights would be greatly appreciated.

Serializable class for Unity

  • SerializableObservableList<T>
  • SerializableObservableDictionary<TKey, TValue>
  • SerializableObservableHashSet<T>
  • SerializableObservableQueue<T>
  • SerializableObservableStack<T>
  • SerializableObservableRingBuffer<T>
  • SerializableObservableFixedSizeRingBuffer<T>

Getting old and new index in ChangeKind.Moved

Hi, components like Vertical/HorizontalLayoutGroup arrange their elements based on relative order of children inside parent GameObjects. This means game objects has to be moved too when it moves in underlying ObservableList. I am not sure tho how to do it when ChangeKind.Moved happened as there are no index parameters.

[Edit] Very sorry for all the edits. lost connection and things got messed up.

[?] Seeking a recommendation: QuikGraph integration

I'm interested in integrating ObservableCollection interfaces with QuikGraph to support the use of a directed graph as a model with MVVM architecture, but the complexity of creating an ISynchronizedView or ISortableSynchronizedView for graphs has left me puzzled. In QuikGraph, there are multiple types of collections used to store vertex and edge information, but the most common structure can be summed up as:

  1. A list of <TVertex>
  2. A dictionary mapping <TVertex> to List<TEdge> where TEdge : IEdge<TVertex>. IEdge guarantees that TEdge has TVertex Source and TVertex Target properties.

QuikGraph provides an interface with events for vertex addition / removal and edge addition / removal. We can interpret this to mean that one graph has two "observable" views: the vertex list, and all edges regardless of vertex. We could also view the graph to be a Dictionary<TVertex, List<TEdge>>, but this would imply an ObservableDictionary<TVertex, ObservableList<TEdge>>... and this brings us back to the integration problem.

Putting aside the QuikGraph dependency for a moment, what would be a valid synchronized view for a graph? Some ideas...

  • Implement IObservableCollection for both <TVertex> and <TEdge>, and require CreateView to be used via IObservableCollection<>.CreateView
  • Layer IObservableCollection such that one view allows for the creation of another view, i.e. IObservableCollection<KeyValuePair<TVertex, IObservableCollection<TEdge>>>. (big code smell here)
  • Instead of implementing interfaces directly on the Graph class, have public IObservableCollection properties for vertices and edges
  • Create an entirely new IObservableDataTable interface and do not treat inter-collection "relations" as additional collection objects <- This might be the conceptually soundest solution.

I'd be thrilled if I could get some advice on observing these sorts of complex collections.

Tasks

  • HashSet
  • Queue
  • Stack
  • RingBuffer
  • Unit Tests
  • WPF Check
  • Blazor Check
  • Unity Check
  • CI(Debug)
  • ReadMe
  • NuGet
  • CI(Release)

-[ ] GroupedView
-[ ] LinkedList

ObservableDictionary doesn't seem to work well in WPF

I clone the repo and edit the wpf test like below:

// ObservableCollections\sandbox\WpfApp\MainWindow.xaml.cs
// ...
public class ViewModel
{
    private ObservableDictionary<int, int> observableList { get; } = [];

    public INotifyCollectionChangedSynchronizedView<int> ItemsView { get; }

    public ReactiveCommand<Unit> ClearCommand { get; } = new ReactiveCommand<Unit>();

    public ReactiveCommand<Unit> RemoveCommand { get; } = new ReactiveCommand<Unit>();

    public ViewModel()
    {
        observableList.Add(1, 1);
        observableList.Add(2, 2);

        ItemsView = observableList.CreateView(x => x.Value).ToNotifyCollectionChanged();

        BindingOperations.EnableCollectionSynchronization(ItemsView, new object());

        // var iii = 10;
        ClearCommand.Subscribe(_ =>
        {
            // observableList.Add(iii++);
            observableList.Clear();
        });

        RemoveCommand.Subscribe(_ =>
        {
            observableList.Remove(1);
        });
    }
}
// ...
// ObservableCollections\sandbox\WpfApp\MainWindow.xaml
// ...
<StackPanel>
    <ListBox ItemsSource="{Binding ItemsView}"/>
    <Button Content="Clear" Command="{Binding ClearCommand}" />
    <Button Content="Remove 1" Command="{Binding RemoveCommand}" />
</StackPanel>
// ...

Run the application, and click the remove button. It thows InvalidOperation with message Collection Remove event must specify item position.
Stack trace below:

at MS.Internal.Data.EnumerableCollectionView.ProcessCollectionChanged(NotifyCollectionChangedEventArgs args)
at System.Windows.Data.CollectionView.PostChange(NotifyCollectionChangedEventArgs args)
at ObservableCollections.Internal.NotifyCollectionChangedSynchronizedView2.OnCollectionChanged(SynchronizedViewChangedEventArgs2& args) in D:\Documents\ObservableCollections\src\ObservableCollections\Internal\NotifyCollectionChangedSynchronizedView.cs:line 72
at ObservableCollections.Internal.NotifyCollectionChangedSynchronizedView2.ObservableCollections.ISynchronizedViewFilter<T,TView>.OnCollectionChanged(SynchronizedViewChangedEventArgs2& eventArgs)
at ObservableCollections.SynchronizedViewFilterExtensions.InvokeOnRemove[T,TView](ISynchronizedViewFilter2 filter, T value, TView view, Int32 oldIndex) in D:\Documents\ObservableCollections\src\ObservableCollections\ISynchronizedViewFilter.cs:line 103 at ObservableCollections.ObservableDictionary2.View1.SourceCollectionChanged(NotifyCollectionChangedEventArgs1& e) in D:\Documents\ObservableCollections\src\ObservableCollections\ObservableDictionary.Views.cs:line 145
at ObservableCollections.ObservableDictionary2.Remove(TKey key) in D:\Documents\ObservableCollections\src\ObservableCollections\ObservableDictionary.cs:line 176 at WpfApp.ViewModel.<.ctor>b__12_2(Unit _) in D:\Documents\ObservableCollections\sandbox\WpfApp\MainWindow.xaml.cs:line 100 at R3.AnonymousObserver1.OnNextCore(T value)

Synchronizing FixedRingBuffer with another ObservableCollection

Hi, I'm trying to implement a looping scroll view in Unity with an ObservableRingBuffer to recycle views and an ObservableList to maintain the data. Something like this:

`

   protected internal ObservableList<IDataContainer> Containers = new();
   protected internal ObservableFixedSizeRingBuffer<View> ViewCache = new();
   ISynchronizedView<IDataContainer, View> SynchronizedViews = Containers.CreateView(EnsureView);
  
   protected View EnsureView(IDataContainer dataContainer)
   {
      var view = ViewCache.RemoveFirst();

      if (!ViewFactory.Verify(dataContainer, view))
      {
           view.Dispose();
           view = viewPoolManager.GetView(ViewFactory.GetViewPrefab(dataContainer), parent);
      }

      ViewCache.AddLast(view);
      return view;
   }

`

This setup works mostly fine until I begin removing dataContainers at which point it becomes really difficult to maintain order.
I've tried using a filter and rotating the indexes of containers as containers are added and removed but I'm getting a lot of Null references when trying to utilize the SynchronizedView.

Id appreciate any advice or suggestions from anyone on how I can get this to work.

Thanks!

WPF example is behaving weirdly

Hi there,

First let me thank you for the massive and impressive work you did with this library! Observable collections are really something that should get more love in the .Net ecosystem :)

I noticed something strange with the WPF example that you provide. When I run it locally and press a few times on the "Insert" button, I get the following :

image

The first 3 lines (in red) correspond to the initial items inserted via AddRange and is the tuple (value, view), while the rest (in green) has been added by pressing the "Insert" button and is only the value.

I do not understand why there is a difference, do you have any idea what could be the reason?

I'm also questioning yielding tuples (value, view) when enumerating, instead of only views. Tuples cannot be used directly for <ListView ItemSource={...} />. Is there a reason for this choice?

In WPF, is it necessary to re-ToNotifyCollectionChanged after re-assigning an ObservableList?

// WPF simple sample.

ObservableList<int> list;
public ISynchronizedView<int, int> ItemsView { get; set; }

public MainWindow()
{
    InitializeComponent();
    this.DataContext = this;

    list = new ObservableList<int>();
    ItemsView = list.CreateView(x => x).ToNotifyCollectionChanged();

    BindingOperations.EnableCollectionSynchronization(ItemsView, new object()); // for ui synchronization safety of viewmodel
}

protected override void OnClosed(EventArgs e)
{
    ItemsView.Dispose();
}

private void DoStuff()
{
    list = GetData();
    // ๐Ÿ‘‡??? Should I always Clear the list and then AddRange the data?
    ItemsView = list.CreateView(x => x).ToNotifyCollectionChanged();

    BindingOperations.EnableCollectionSynchronization(ItemsView, new object()); // for ui synchronization safety of viewmodel
}

ToNotifyCollectionChanged: Collection.Clear() causes InvalidOperationException when binding to ListBox(WPF)

The following code will cause an InvalidOperationException when ObservableList.Clear() is executed.

<Window x:Class="WpfApp1.MainWindow" ...>
    <StackPanel>
        <ListBox ItemsSource="{Binding ItemsView}" />
        <Button Content="Clear" Command="{Binding ClearCommand}" />
    </StackPanel>
</Window>
using ObservableCollections;
using R3;
using System.Windows.Data;

namespace WpfApp1
{
    class ViewModel
    {
        private ObservableList<int> observableList { get; } = new ObservableList<int>();
        public INotifyCollectionChangedSynchronizedView<int> ItemsView { get; }
        public ReactiveCommand<Unit> ClearCommand { get; } = new ReactiveCommand<Unit>();
        
        public ViewModel()
        {
            observableList.Add(1);
            observableList.Add(2);

            ItemsView = observableList.CreateView(x => x).ToNotifyCollectionChanged();

            BindingOperations.EnableCollectionSynchronization(ItemsView, new object());

            ClearCommand.Subscribe(_ => observableList.Clear());
        }
    }
}
R3 UnhandledException:System.InvalidOperationException: Collection Remove event must specify item position.
   at MS.Internal.Data.EnumerableCollectionView.ProcessCollectionChanged(NotifyCollectionChangedEventArgs args)
   at System.Windows.Data.CollectionView.PostChange(NotifyCollectionChangedEventArgs args)
   at ObservableCollections.Internal.NotifyCollectionChangedSynchronizedView`2.OnCollectionChanged(ChangedKind changedKind, T value, TView view, NotifyCollectionChangedEventArgs`1& eventArgs) in C:\Source\ObservableCollections-2.0.2\src\ObservableCollections\Internal\NotifyCollectionChangedSynchronizedView.cs:line 72
   at ObservableCollections.Internal.NotifyCollectionChangedSynchronizedView`2.ObservableCollections.ISynchronizedViewFilter<T,TView>.OnCollectionChanged(ChangedKind changedKind, T value, TView view, NotifyCollectionChangedEventArgs`1& eventArgs)
   at ObservableCollections.SynchronizedViewFilterExtensions.InvokeOnRemove[T,TView](ISynchronizedViewFilter`2 filter, T value, TView view, NotifyCollectionChangedEventArgs`1& eventArgs) in C:\Source\ObservableCollections-2.0.2\src\ObservableCollections\ISynchronizedViewFilter.cs:line 96
   at ObservableCollections.SynchronizedViewFilterExtensions.InvokeOnRemove[T,TView](ISynchronizedViewFilter`2 filter, ValueTuple`2 value, NotifyCollectionChangedEventArgs`1& eventArgs) in C:\Source\ObservableCollections-2.0.2\src\ObservableCollections\ISynchronizedViewFilter.cs:line 91
   at ObservableCollections.ObservableList`1.View`1.SourceCollectionChanged(NotifyCollectionChangedEventArgs`1& e) in C:\Source\ObservableCollections-2.0.2\src\ObservableCollections\ObservableList.Views.cs:line 237
   at ObservableCollections.ObservableList`1.Clear() in C:\Source\ObservableCollections-2.0.2\src\ObservableCollections\ObservableList.cs:line 118
   at WpfApp1.ViewModel.<.ctor>b__9_1(Unit _) in C:\Source\WpfApp1\ViewModel.cs:line 22
   at R3.AnonymousObserver`1.OnNextCore(T value)
   at R3.Observer`1.OnNext(T value)

It occurs because eventArgs.OldStartingIndex is -1, which is created by NotifyCollectionChangedEventArgs<T>.Reset().

case ChangedKind.Remove:
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, view, eventArgs.OldStartingIndex));
PropertyChanged?.Invoke(this, CountPropertyChangedEventArgs);
break;

case NotifyCollectionChangedAction.Reset:
if (!filter.IsNullFilter())
{
foreach (var item in list)
{
filter.InvokeOnRemove(item, e);
}
}
list.Clear();
break;

I tried fixing ObservableList.View, but could not figure out how to fix ObservableDictionary, ObservableHashSet... that does not have Index.

--- a/src/ObservableCollections/ObservableList.Views.cs
+++ b/src/ObservableCollections/ObservableList.Views.cs
@@ -232,9 +232,10 @@ namespace ObservableCollections
                         case NotifyCollectionChangedAction.Reset:
                             if (!filter.IsNullFilter())
                             {
-                                foreach (var item in list)
+                                for (var i = list.Count - 1; i >= 0; i--)
                                 {
-                                    filter.InvokeOnRemove(item, e);
+                                    var item = list[i];
+                                    filter.InvokeOnRemove(item, NotifyCollectionChangedEventArgs<T>.Remove(item.Item1, i));
                                 }
                             }
                             list.Clear();

dotnet/efcore#7397 Same problem encountered with non-indexed collections and ListBox.

Miss set the item to the array

        public CloneCollection(T item)
        {
            this.array = ArrayPool<T>.Shared.Rent(1); // And I do not think rent the array which the lenght is one form pool is a good way.
            this.length = 1;
           // Miss:  this.array[0] = item;
        }

Did you forget to assign a value to the variable?

Thank you,

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.