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
|
```csharp
|
||||||
// WPF simple sample.
|
// WPF simple sample.
|
||||||
@ -222,9 +222,12 @@ public MainWindow()
|
|||||||
this.DataContext = this;
|
this.DataContext = this;
|
||||||
|
|
||||||
list = new ObservableList<int>();
|
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)
|
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.
|
> 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
|
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.
|
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>-->
|
</Grid>-->
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<ListBox ItemsSource="{Binding ItemsView}" />
|
<ListBox ItemsSource="{Binding ItemsView}" />
|
||||||
|
<Button Content="Add" Command="{Binding AddCommand}" />
|
||||||
<Button Content="Clear" Command="{Binding ClearCommand}" />
|
<Button Content="Clear" Command="{Binding ClearCommand}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Window>
|
</Window>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using R3;
|
using R3;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -16,6 +17,7 @@ using System.Windows.Media;
|
|||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using System.Windows.Navigation;
|
using System.Windows.Navigation;
|
||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
|
using System.Windows.Threading;
|
||||||
|
|
||||||
namespace WpfApp
|
namespace WpfApp
|
||||||
{
|
{
|
||||||
@ -42,7 +44,7 @@ namespace WpfApp
|
|||||||
|
|
||||||
this.DataContext = new ViewModel();
|
this.DataContext = new ViewModel();
|
||||||
|
|
||||||
|
// Dispatcher.BeginInvoke(
|
||||||
|
|
||||||
|
|
||||||
//list = new ObservableList<int>();
|
//list = new ObservableList<int>();
|
||||||
@ -73,6 +75,7 @@ namespace WpfApp
|
|||||||
{
|
{
|
||||||
private ObservableList<int> observableList { get; } = new ObservableList<int>();
|
private ObservableList<int> observableList { get; } = new ObservableList<int>();
|
||||||
public INotifyCollectionChangedSynchronizedView<int> ItemsView { get; }
|
public INotifyCollectionChangedSynchronizedView<int> ItemsView { get; }
|
||||||
|
public ReactiveCommand<Unit> AddCommand { get; } = new ReactiveCommand<Unit>();
|
||||||
public ReactiveCommand<Unit> ClearCommand { get; } = new ReactiveCommand<Unit>();
|
public ReactiveCommand<Unit> ClearCommand { get; } = new ReactiveCommand<Unit>();
|
||||||
|
|
||||||
public ViewModel()
|
public ViewModel()
|
||||||
@ -80,9 +83,20 @@ namespace WpfApp
|
|||||||
observableList.Add(1);
|
observableList.Add(1);
|
||||||
observableList.Add(2);
|
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;
|
// var iii = 10;
|
||||||
ClearCommand.Subscribe(_ =>
|
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>
|
<PropertyGroup>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net6.0-windows</TargetFramework>
|
<TargetFramework>net6.0-windows</TargetFramework>
|
||||||
|
<LangVersion>12</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
<IsPackable>false</IsPackable>
|
<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 AttachFilter(ISynchronizedViewFilter<T, TView> filter, bool invokeAddEventForInitialElements = false);
|
||||||
void ResetFilter(Action<T, TView>? resetAction);
|
void ResetFilter(Action<T, TView>? resetAction);
|
||||||
INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged();
|
INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged();
|
||||||
|
INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ISortableSynchronizedView<T, TView> : ISynchronizedView<T, TView>
|
public interface ISortableSynchronizedView<T, TView> : ISynchronizedView<T, TView>
|
||||||
|
@ -114,7 +114,12 @@ namespace ObservableCollections.Internal
|
|||||||
|
|
||||||
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged()
|
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()
|
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)>
|
class TComparer : IComparer<(T, TView)>
|
||||||
|
@ -11,13 +11,16 @@ namespace ObservableCollections.Internal
|
|||||||
ISynchronizedViewFilter<T, TView>
|
ISynchronizedViewFilter<T, TView>
|
||||||
{
|
{
|
||||||
static readonly PropertyChangedEventArgs CountPropertyChangedEventArgs = new("Count");
|
static readonly PropertyChangedEventArgs CountPropertyChangedEventArgs = new("Count");
|
||||||
|
static readonly Action<NotifyCollectionChangedEventArgs> raiseChangedEventInvoke = RaiseChangedEvent;
|
||||||
|
|
||||||
readonly ISynchronizedView<T, TView> parent;
|
readonly ISynchronizedView<T, TView> parent;
|
||||||
readonly ISynchronizedViewFilter<T, TView> currentFilter;
|
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.parent = parent;
|
||||||
|
this.eventDispatcher = eventDispatcher ?? DirectCollectionEventDispatcher.Instance;
|
||||||
currentFilter = parent.CurrentFilter;
|
currentFilter = parent.CurrentFilter;
|
||||||
parent.AttachFilter(this);
|
parent.AttachFilter(this);
|
||||||
}
|
}
|
||||||
@ -62,27 +65,71 @@ namespace ObservableCollections.Internal
|
|||||||
{
|
{
|
||||||
currentFilter.OnCollectionChanged(args);
|
currentFilter.OnCollectionChanged(args);
|
||||||
|
|
||||||
|
if (CollectionChanged == null && PropertyChanged == null) return;
|
||||||
|
|
||||||
switch (args.Action)
|
switch (args.Action)
|
||||||
{
|
{
|
||||||
case NotifyCollectionChangedAction.Add:
|
case NotifyCollectionChangedAction.Add:
|
||||||
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, args.NewView, args.NewViewIndex));
|
eventDispatcher.Post(new CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction.Add, args.NewView, args.NewViewIndex)
|
||||||
PropertyChanged?.Invoke(this, CountPropertyChangedEventArgs);
|
{
|
||||||
|
Collection = this,
|
||||||
|
Invoker = raiseChangedEventInvoke,
|
||||||
|
IsInvokeCollectionChanged = true,
|
||||||
|
IsInvokePropertyChanged = true
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case NotifyCollectionChangedAction.Remove:
|
case NotifyCollectionChangedAction.Remove:
|
||||||
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, args.OldView, args.OldViewIndex));
|
eventDispatcher.Post(new CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction.Remove, args.OldView, args.OldViewIndex)
|
||||||
PropertyChanged?.Invoke(this, CountPropertyChangedEventArgs);
|
{
|
||||||
|
Collection = this,
|
||||||
|
Invoker = raiseChangedEventInvoke,
|
||||||
|
IsInvokeCollectionChanged = true,
|
||||||
|
IsInvokePropertyChanged = true
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case NotifyCollectionChangedAction.Reset:
|
case NotifyCollectionChangedAction.Reset:
|
||||||
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
eventDispatcher.Post(new CollectionEventDispatcherEventArgs(NotifyCollectionChangedAction.Reset)
|
||||||
PropertyChanged?.Invoke(this, CountPropertyChangedEventArgs);
|
{
|
||||||
|
Collection = this,
|
||||||
|
Invoker = raiseChangedEventInvoke,
|
||||||
|
IsInvokeCollectionChanged = true,
|
||||||
|
IsInvokePropertyChanged = true
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case NotifyCollectionChangedAction.Replace:
|
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;
|
break;
|
||||||
case NotifyCollectionChangedAction.Move:
|
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;
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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