diff --git a/src/Simplify.Wpf/Extensions/ObservableCollectionExtensions.cs b/src/Simplify.Wpf/Extensions/ObservableCollectionExtensions.cs new file mode 100644 index 00000000..bc840956 --- /dev/null +++ b/src/Simplify.Wpf/Extensions/ObservableCollectionExtensions.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.ObjectModel; +using System.Windows.Data; + +namespace Simplify.Wpf.Extensions +{ + /// + /// Provides extensions for the ObservableCollection + /// + public static class ObservableCollectionExtensions + { + /// + /// Enables multi-thread synchronization of ObservableCollection instance + /// + /// ObservableCollection instance + /// + /// + /// + public static ObservableCollection EnableSynchronization(this ObservableCollection collection, object? lockObject = null) + { + if (collection is null) + throw new ArgumentNullException(nameof(collection), "ObservableCollection instance is Null"); + + BindingOperations.EnableCollectionSynchronization(collection, lockObject ?? new object()); + return collection; + } + } +} \ No newline at end of file diff --git a/src/Simplify.Wpf/Simplify.Wpf.csproj b/src/Simplify.Wpf/Simplify.Wpf.csproj new file mode 100644 index 00000000..8ffd7091 --- /dev/null +++ b/src/Simplify.Wpf/Simplify.Wpf.csproj @@ -0,0 +1,33 @@ + + + net462 + 9.0 + enable + true + true + snupkg + bin\Any CPU\$(Configuration)\ + bin\Any CPU\$(Configuration)\$(TargetFramework)\Simplify.Wpf.xml + + 1.0 + + ObservableCollection synchronization extensions. + SynchronizedObservableCollection class. + + + Simplify community + Simplify + Extensions for the PresentationFramework + Licensed under LGPL + https://github.com/SimplifyNet/Simplify + https://raw.githubusercontent.com/SimplifyNet/Images/master/Logo.png + true + .NET WPF + + + + + + + + \ No newline at end of file diff --git a/src/Simplify.Wpf/SynchronizedObservableCollection.cs b/src/Simplify.Wpf/SynchronizedObservableCollection.cs new file mode 100644 index 00000000..3788f444 --- /dev/null +++ b/src/Simplify.Wpf/SynchronizedObservableCollection.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Simplify.System; +using Simplify.Wpf.Extensions; + +namespace Simplify.Wpf +{ + /// + /// Provides multi-thread synchronized ObservableCollection. Implements IConcurrentResource. + /// + /// Data type + public class SynchronizedObservableCollection : ObservableCollection, IConcurrentResource + { + private readonly object _locker = new(); + + /// + /// Creates instance of SynchronizedObservableCollection. + /// + public SynchronizedObservableCollection() + { + this.EnableSynchronization(_locker); + } + + /// + /// Creates instance of SynchronizedObservableCollection. + /// + /// + public SynchronizedObservableCollection(List list) : base(list) + { + this.EnableSynchronization(_locker); + } + + /// + /// Creates instance of SynchronizedObservableCollection. + /// + /// + public SynchronizedObservableCollection(IEnumerable collection) : base(collection) + { + this.EnableSynchronization(_locker); + } + + /// + /// Invoke the action concurrently + /// + /// Action over current collection + public void InvokeConcurrently(Action action) + { + if (action is null) throw new ArgumentNullException(nameof(action)); + lock (_locker) action(); + } + } +} \ No newline at end of file diff --git a/src/Simplify.sln b/src/Simplify.sln index deeaef2d..900cbbbf 100644 --- a/src/Simplify.sln +++ b/src/Simplify.sln @@ -137,6 +137,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Simplify.FluentNHibernate.E EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Simplify.FluentNHibernate.Examples.Database.IntegrationTests", "Examples\Simplify.FluentNHibernate.Examples.Database.IntegrationTests\Simplify.FluentNHibernate.Examples.Database.IntegrationTests.csproj", "{A772A1FC-2AF8-4411-883D-3646339009BE}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WPF", "WPF", "{B2CDEA39-00C4-4285-9730-EA6C50011D20}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Simplify.Wpf", "Simplify.Wpf\Simplify.Wpf.csproj", "{0C1DF149-F9ED-471A-8EBF-B212A9CA7C5B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -323,6 +327,10 @@ Global {A772A1FC-2AF8-4411-883D-3646339009BE}.Debug|Any CPU.Build.0 = Debug|Any CPU {A772A1FC-2AF8-4411-883D-3646339009BE}.Release|Any CPU.ActiveCfg = Release|Any CPU {A772A1FC-2AF8-4411-883D-3646339009BE}.Release|Any CPU.Build.0 = Release|Any CPU + {0C1DF149-F9ED-471A-8EBF-B212A9CA7C5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C1DF149-F9ED-471A-8EBF-B212A9CA7C5B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C1DF149-F9ED-471A-8EBF-B212A9CA7C5B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C1DF149-F9ED-471A-8EBF-B212A9CA7C5B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -378,6 +386,7 @@ Global {09BC064D-3174-4FDE-B87F-0F21BA067A5D} = {2D057C2A-06BD-48F2-A075-B6EC42D39007} {1A825EB4-13D4-45D0-9925-C6AADC3D47EF} = {2D057C2A-06BD-48F2-A075-B6EC42D39007} {A772A1FC-2AF8-4411-883D-3646339009BE} = {2D057C2A-06BD-48F2-A075-B6EC42D39007} + {0C1DF149-F9ED-471A-8EBF-B212A9CA7C5B} = {B2CDEA39-00C4-4285-9730-EA6C50011D20} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {466E8FF6-456A-4262-A9ED-5E88DB8DCB08}