Add ICollectionEventDispatcher, ToNotifyCollectionChanged(ICollectionEventDispatcher)
This commit is contained in:
parent
7e139dc57a
commit
a99b10ca49
27
README.md
27
README.md
@ -206,9 +206,9 @@ public partial class DataTable<T> : ComponentBase, IDisposable
|
||||
}
|
||||
```
|
||||
|
||||
WPF
|
||||
WPF/Avalonia
|
||||
---
|
||||
Because of data binding in WPF, it is important that the collection is Observable. ObservableCollections high-performance `IObservableCollection<T>` cannot be bind to WPF. Call `ToNotifyCollectionChanged()` to convert it to `INotifyCollectionChanged`. Also, although ObservableCollections and Views are thread-safe, the WPF UI does not support change notifications from different threads. `BindingOperations.EnableCollectionSynchronization` to work safely with change notifications from different threads.
|
||||
Because of data binding in WPF, it is important that the collection is Observable. ObservableCollections high-performance `IObservableCollection<T>` cannot be bind to WPF. Call `ToNotifyCollectionChanged()` to convert it to `INotifyCollectionChanged`. Also, although ObservableCollections and Views are thread-safe, the WPF UI does not support change notifications from different threads. To`ToNotifyCollectionChanged(IColllectionEventDispatcher)` allows multi thread changed.
|
||||
|
||||
```csharp
|
||||
// WPF simple sample.
|
||||
@ -222,9 +222,12 @@ public MainWindow()
|
||||
this.DataContext = this;
|
||||
|
||||
list = new ObservableList<int>();
|
||||
ItemsView = list.CreateView(x => x).ToNotifyCollectionChanged();
|
||||
|
||||
BindingOperations.EnableCollectionSynchronization(ItemsView, new object()); // for ui synchronization safety of viewmodel
|
||||
// for ui synchronization safety of viewmodel
|
||||
ItemsView = list.CreateView(x => x).ToNotifyCollectionChanged(SynchronizationContextCollectionEventDispatcher.Current);
|
||||
|
||||
// if collection is changed only from ui-thread, can use this overload
|
||||
// ItemsView = list.CreateView(x => x).ToNotifyCollectionChanged();
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
@ -235,6 +238,22 @@ protected override void OnClosed(EventArgs e)
|
||||
|
||||
> WPF can not use SortedView because SortedView can not provide sort event to INotifyCollectionChanged.
|
||||
|
||||
`SynchronizationContextCollectionEventDispatcher.Current` is default implementation of `IColllectionEventDispatcher`, it is used `SynchronizationContext.Current` for dispatche ui thread. You can create custom `ICollectionEventDispatcher` to use custom dispatcher object. For example use WPF Dispatcher:
|
||||
|
||||
```csharp
|
||||
public class WpfDispatcherCollection(Dispatcher dispatcher) : ICollectionEventDispatcher
|
||||
{
|
||||
public void Post(CollectionEventDispatcherEventArgs ev)
|
||||
{
|
||||
dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
// notify in dispatcher
|
||||
ev.Invoke();
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Unity
|
||||
---
|
||||
In Unity projects, you can installing `ObservableCollections` with [NugetForUnity](https://github.com/GlitchEnzo/NuGetForUnity). If R3 integration is required, similarly install `ObservableCollections.R3` via NuGetForUnity.
|
||||
|
@ -19,6 +19,7 @@
|
||||
</Grid>-->
|
||||
<StackPanel>
|
||||
<ListBox ItemsSource="{Binding ItemsView}" />
|
||||
<Button Content="Add" Command="{Binding AddCommand}" />
|
||||
<Button Content="Clear" Command="{Binding ClearCommand}" />
|
||||
</StackPanel>
|
||||
</Window>
|
||||
|
@ -2,6 +2,7 @@
|
||||
using R3;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@ -16,6 +17,7 @@ using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace WpfApp
|
||||
{
|
||||
@ -42,7 +44,7 @@ namespace WpfApp
|
||||
|
||||
this.DataContext = new ViewModel();
|
||||
|
||||
|
||||
// Dispatcher.BeginInvoke(
|
||||
|
||||
|
||||
//list = new ObservableList<int>();
|
||||
@ -73,6 +75,7 @@ namespace WpfApp
|
||||
{
|
||||
private ObservableList<int> observableList { get; } = new ObservableList<int>();
|
||||
public INotifyCollectionChangedSynchronizedView<int> ItemsView { get; }
|
||||
public ReactiveCommand<Unit> AddCommand { get; } = new ReactiveCommand<Unit>();
|
||||
public ReactiveCommand<Unit> ClearCommand { get; } = new ReactiveCommand<Unit>();
|
||||
|
||||
public ViewModel()
|
||||
@ -80,9 +83,20 @@ namespace WpfApp
|
||||
observableList.Add(1);
|
||||
observableList.Add(2);
|
||||
|
||||
ItemsView = observableList.CreateView(x => x).ToNotifyCollectionChanged();
|
||||
ItemsView = observableList.CreateView(x => x).ToNotifyCollectionChanged(SynchronizationContextCollectionEventDispatcher.Current);
|
||||
|
||||
BindingOperations.EnableCollectionSynchronization(ItemsView, new object());
|
||||
|
||||
// ItemsView = observableList.CreateView(x => x).ToNotifyCollectionChanged();
|
||||
|
||||
// BindingOperations.EnableCollectionSynchronization(ItemsView, new object());
|
||||
|
||||
AddCommand.Subscribe(_ =>
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(_ =>
|
||||
{
|
||||
observableList.Add(Random.Shared.Next());
|
||||
});
|
||||
});
|
||||
|
||||
// var iii = 10;
|
||||
ClearCommand.Subscribe(_ =>
|
||||
@ -92,4 +106,15 @@ namespace WpfApp
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class WpfDispatcherCollection(Dispatcher dispatcher) : ICollectionEventDispatcher
|
||||
{
|
||||
public void Post(CollectionEventDispatcherEventArgs ev)
|
||||
{
|
||||
dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
ev.Invoke();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<UseWPF>true</UseWPF>
|
||||
<IsPackable>false</IsPackable>
|
||||
|
119
src/ObservableCollections/ICollectionEventDispatcher.cs
Normal file
119
src/ObservableCollections/ICollectionEventDispatcher.cs
Normal file
@ -0,0 +1,119 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System.Threading;
|
||||
|
||||
namespace ObservableCollections
|
||||
{
|
||||
public interface ICollectionEventDispatcher
|
||||
{
|
||||
void Post(CollectionEventDispatcherEventArgs ev);
|
||||
}
|
||||
|
||||
public class SynchronizationContextCollectionEventDispatcher : ICollectionEventDispatcher
|
||||
{
|
||||
static readonly Lazy<ICollectionEventDispatcher> current = new Lazy<ICollectionEventDispatcher>(() =>
|
||||
{
|
||||
var current = SynchronizationContext.Current;
|
||||
if (current == null)
|
||||
{
|
||||
throw new InvalidOperationException("SynchronizationContext.Current is null");
|
||||
}
|
||||
|
||||
return new SynchronizationContextCollectionEventDispatcher(current);
|
||||
});
|
||||
|
||||
public static readonly ICollectionEventDispatcher Current = current.Value;
|
||||
|
||||
readonly SynchronizationContext synchronizationContext;
|
||||
static readonly SendOrPostCallback callback = SendOrPostCallback;
|
||||
|
||||
public SynchronizationContextCollectionEventDispatcher(SynchronizationContext synchronizationContext)
|
||||
{
|
||||
this.synchronizationContext = synchronizationContext;
|
||||
}
|
||||
|
||||
public void Post(CollectionEventDispatcherEventArgs ev)
|
||||
{
|
||||
synchronizationContext.Post(callback, ev);
|
||||
}
|
||||
|
||||
static void SendOrPostCallback(object? state)
|
||||
{
|
||||
var ev = (CollectionEventDispatcherEventArgs)state!;
|
||||
ev.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
internal class DirectCollectionEventDispatcher : ICollectionEventDispatcher
|
||||
{
|
||||
public static readonly ICollectionEventDispatcher Instance = new DirectCollectionEventDispatcher();
|
||||
|
||||
DirectCollectionEventDispatcher()
|
||||
{
|
||||
}
|
||||
|
||||
public void Post(CollectionEventDispatcherEventArgs ev)
|
||||
{
|
||||
ev.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
public class CollectionEventDispatcherEventArgs : NotifyCollectionChangedEventArgs
|
||||
{
|
||||
// +state, init;
|
||||
public object Collection { get; set; } = default!;
|
||||
public bool IsInvokeCollectionChanged { get; set; }
|
||||
public bool IsInvokePropertyChanged { get; set; }
|
||||
internal Action<CollectionEventDispatcherEventArgs> Invoker { get; set; } = default!;
|
||||
|
||||
public void Invoke()
|
||||
{
|
||||
Invoker.Invoke(this);
|
||||
}
|
||||
|
||||
public CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction action) : base(action)
|
||||
{
|
||||
}
|
||||
|
||||
public CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction action, IList? changedItems) : base(action, changedItems)
|
||||
{
|
||||
}
|
||||
|
||||
public CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction action, object? changedItem) : base(action, changedItem)
|
||||
{
|
||||
}
|
||||
|
||||
public CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction action, IList newItems, IList oldItems) : base(action, newItems, oldItems)
|
||||
{
|
||||
}
|
||||
|
||||
public CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction action, IList? changedItems, int startingIndex) : base(action, changedItems, startingIndex)
|
||||
{
|
||||
}
|
||||
|
||||
public CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction action, object? changedItem, int index) : base(action, changedItem, index)
|
||||
{
|
||||
}
|
||||
|
||||
public CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction action, object? newItem, object? oldItem) : base(action, newItem, oldItem)
|
||||
{
|
||||
}
|
||||
|
||||
public CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex) : base(action, newItems, oldItems, startingIndex)
|
||||
{
|
||||
}
|
||||
|
||||
public CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction action, IList? changedItems, int index, int oldIndex) : base(action, changedItems, index, oldIndex)
|
||||
{
|
||||
}
|
||||
|
||||
public CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction action, object? changedItem, int index, int oldIndex) : base(action, changedItem, index, oldIndex)
|
||||
{
|
||||
}
|
||||
|
||||
public CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction action, object? newItem, object? oldItem, int index) : base(action, newItem, oldItem, index)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -37,6 +37,7 @@ namespace ObservableCollections
|
||||
void AttachFilter(ISynchronizedViewFilter<T, TView> filter, bool invokeAddEventForInitialElements = false);
|
||||
void ResetFilter(Action<T, TView>? resetAction);
|
||||
INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged();
|
||||
INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher);
|
||||
}
|
||||
|
||||
public interface ISortableSynchronizedView<T, TView> : ISynchronizedView<T, TView>
|
||||
|
@ -114,7 +114,12 @@ namespace ObservableCollections.Internal
|
||||
|
||||
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged()
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this);
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, null);
|
||||
}
|
||||
|
||||
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, collectionEventDispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,7 +223,12 @@ namespace ObservableCollections.Internal
|
||||
|
||||
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged()
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this);
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, null);
|
||||
}
|
||||
|
||||
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, collectionEventDispatcher);
|
||||
}
|
||||
|
||||
class TComparer : IComparer<(T, TView)>
|
||||
|
@ -11,13 +11,16 @@ namespace ObservableCollections.Internal
|
||||
ISynchronizedViewFilter<T, TView>
|
||||
{
|
||||
static readonly PropertyChangedEventArgs CountPropertyChangedEventArgs = new("Count");
|
||||
static readonly Action<NotifyCollectionChangedEventArgs> raiseChangedEventInvoke = RaiseChangedEvent;
|
||||
|
||||
readonly ISynchronizedView<T, TView> parent;
|
||||
readonly ISynchronizedViewFilter<T, TView> currentFilter;
|
||||
readonly ICollectionEventDispatcher eventDispatcher;
|
||||
|
||||
public NotifyCollectionChangedSynchronizedView(ISynchronizedView<T, TView> parent)
|
||||
public NotifyCollectionChangedSynchronizedView(ISynchronizedView<T, TView> parent, ICollectionEventDispatcher? eventDispatcher)
|
||||
{
|
||||
this.parent = parent;
|
||||
this.eventDispatcher = eventDispatcher ?? DirectCollectionEventDispatcher.Instance;
|
||||
currentFilter = parent.CurrentFilter;
|
||||
parent.AttachFilter(this);
|
||||
}
|
||||
@ -62,27 +65,71 @@ namespace ObservableCollections.Internal
|
||||
{
|
||||
currentFilter.OnCollectionChanged(args);
|
||||
|
||||
if (CollectionChanged == null && PropertyChanged == null) return;
|
||||
|
||||
switch (args.Action)
|
||||
{
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, args.NewView, args.NewViewIndex));
|
||||
PropertyChanged?.Invoke(this, CountPropertyChangedEventArgs);
|
||||
eventDispatcher.Post(new CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction.Add, args.NewView, args.NewViewIndex)
|
||||
{
|
||||
Collection = this,
|
||||
Invoker = raiseChangedEventInvoke,
|
||||
IsInvokeCollectionChanged = true,
|
||||
IsInvokePropertyChanged = true
|
||||
});
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, args.OldView, args.OldViewIndex));
|
||||
PropertyChanged?.Invoke(this, CountPropertyChangedEventArgs);
|
||||
eventDispatcher.Post(new CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction.Remove, args.OldView, args.OldViewIndex)
|
||||
{
|
||||
Collection = this,
|
||||
Invoker = raiseChangedEventInvoke,
|
||||
IsInvokeCollectionChanged = true,
|
||||
IsInvokePropertyChanged = true
|
||||
});
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Reset:
|
||||
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
PropertyChanged?.Invoke(this, CountPropertyChangedEventArgs);
|
||||
eventDispatcher.Post(new CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction.Reset)
|
||||
{
|
||||
Collection = this,
|
||||
Invoker = raiseChangedEventInvoke,
|
||||
IsInvokeCollectionChanged = true,
|
||||
IsInvokePropertyChanged = true
|
||||
});
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Replace:
|
||||
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, args.NewView, args.OldView, args.NewViewIndex));
|
||||
eventDispatcher.Post(new CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction.Replace, args.NewView, args.OldView, args.NewViewIndex)
|
||||
{
|
||||
Collection = this,
|
||||
Invoker = raiseChangedEventInvoke,
|
||||
IsInvokeCollectionChanged = true,
|
||||
IsInvokePropertyChanged = false
|
||||
});
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Move:
|
||||
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, args.NewView, args.NewViewIndex, args.OldViewIndex));
|
||||
eventDispatcher.Post(new CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction.Move, args.NewView, args.NewViewIndex, args.OldViewIndex)
|
||||
{
|
||||
Collection = this,
|
||||
Invoker = raiseChangedEventInvoke,
|
||||
IsInvokeCollectionChanged = true,
|
||||
IsInvokePropertyChanged = false
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void RaiseChangedEvent(NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
var e2 = (CollectionEventDispatcherEventArgs)e;
|
||||
var self = (NotifyCollectionChangedSynchronizedView<T, TView>)e2.Collection;
|
||||
|
||||
if (e2.IsInvokeCollectionChanged)
|
||||
{
|
||||
self.CollectionChanged?.Invoke(self, e);
|
||||
}
|
||||
if (e2.IsInvokePropertyChanged)
|
||||
{
|
||||
self.PropertyChanged?.Invoke(self, CountPropertyChangedEventArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -94,7 +94,15 @@ namespace ObservableCollections.Internal
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this);
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, collectionEventDispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,15 @@ namespace ObservableCollections.Internal
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this);
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, collectionEventDispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,15 @@ namespace ObservableCollections
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<KeyValuePair<TKey, TValue>, TView>(this);
|
||||
return new NotifyCollectionChangedSynchronizedView<KeyValuePair<TKey, TValue>, TView>(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<KeyValuePair<TKey, TValue>, TView>(this, collectionEventDispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,15 @@ namespace ObservableCollections
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this);
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, collectionEventDispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,15 @@ namespace ObservableCollections
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this);
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, collectionEventDispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,15 @@ namespace ObservableCollections
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this);
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, collectionEventDispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,7 +98,15 @@ namespace ObservableCollections
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this);
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, collectionEventDispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,15 @@ namespace ObservableCollections
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this);
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return new NotifyCollectionChangedSynchronizedView<T, TView>(this, collectionEventDispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user