Skip to content
Merged
28 changes: 28 additions & 0 deletions src/Simplify.Wpf/Extensions/ObservableCollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Collections.ObjectModel;
using System.Windows.Data;

namespace Simplify.Wpf.Extensions
{
/// <summary>
/// Provides extensions for the ObservableCollection
/// </summary>
public static class ObservableCollectionExtensions
{
/// <summary>
/// Enables multi-thread synchronization of ObservableCollection instance
/// </summary>
/// <param name="collection">ObservableCollection instance</param>
/// <param name="lockObject"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static ObservableCollection<T> EnableSynchronization<T>(this ObservableCollection<T> 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;
}
}
}
33 changes: 33 additions & 0 deletions src/Simplify.Wpf/Simplify.Wpf.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net462</TargetFrameworks>
<LangVersion>9.0</LangVersion>
<Nullable>enable</Nullable>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<OutputPath>bin\Any CPU\$(Configuration)\</OutputPath>
<DocumentationFile>bin\Any CPU\$(Configuration)\$(TargetFramework)\Simplify.Wpf.xml</DocumentationFile>

<Version>1.0</Version>
<PackageReleaseNotes>
ObservableCollection synchronization extensions.
SynchronizedObservableCollection class.
</PackageReleaseNotes>

<Authors>Simplify community</Authors>
<Product>Simplify</Product>
<Description>Extensions for the PresentationFramework</Description>
<Copyright>Licensed under LGPL</Copyright>
<PackageProjectUrl>https://github.com/SimplifyNet/Simplify</PackageProjectUrl>
<PackageIconUrl>https://raw.githubusercontent.com/SimplifyNet/Images/master/Logo.png</PackageIconUrl>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<PackageTags>.NET WPF</PackageTags>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Simplify.System" Version="1.5.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="PresentationFramework" />
</ItemGroup>
</Project>
53 changes: 53 additions & 0 deletions src/Simplify.Wpf/SynchronizedObservableCollection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Simplify.System;
using Simplify.Wpf.Extensions;

namespace Simplify.Wpf
{
/// <summary>
/// Provides multi-thread synchronized ObservableCollection. Implements IConcurrentResource.
/// </summary>
/// <typeparam name="T">Data type</typeparam>
public class SynchronizedObservableCollection<T> : ObservableCollection<T>, IConcurrentResource
{
private readonly object _locker = new();

/// <summary>
/// Creates instance of SynchronizedObservableCollection.
/// </summary>
public SynchronizedObservableCollection()
{
this.EnableSynchronization(_locker);
}

/// <summary>
/// Creates instance of SynchronizedObservableCollection.
/// </summary>
/// <param name="list"></param>
public SynchronizedObservableCollection(List<T> list) : base(list)
{
this.EnableSynchronization(_locker);
}

/// <summary>
/// Creates instance of SynchronizedObservableCollection.
/// </summary>
/// <param name="collection"></param>
public SynchronizedObservableCollection(IEnumerable<T> collection) : base(collection)
{
this.EnableSynchronization(_locker);
}

/// <summary>
/// Invoke the action concurrently
/// </summary>
/// <param name="action">Action over current collection</param>
public void InvokeConcurrently(Action action)
{
if (action is null) throw new ArgumentNullException(nameof(action));
lock (_locker) action();
}
}
}
9 changes: 9 additions & 0 deletions src/Simplify.sln
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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}
Expand Down