diff --git a/.editorconfig b/.editorconfig
index b93421537..434fb0c8e 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -10,6 +10,24 @@ root = true
insert_final_newline = true
indent_style = space
indent_size = 4
+dotnet_style_operator_placement_when_wrapping = beginning_of_line
+tab_width = 4
+end_of_line = crlf
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
+dotnet_style_prefer_auto_properties = true:suggestion
+dotnet_style_object_initializer = true:suggestion
+dotnet_style_collection_initializer = true:suggestion
+dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
+dotnet_style_prefer_conditional_expression_over_assignment = true:silent
+dotnet_style_prefer_conditional_expression_over_return = true:silent
+dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_compound_assignment = true:suggestion
+dotnet_style_prefer_simplified_interpolation = true:suggestion
+dotnet_style_namespace_match_folder = true:suggestion
[project.json]
indent_size = 2
@@ -54,7 +72,7 @@ dotnet_style_predefined_type_for_member_access = true:suggestion
# name all constant fields using PascalCase
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
-dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
+dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.constant_fields.applicable_kinds = field
dotnet_naming_symbols.constant_fields.required_modifiers = const
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
@@ -62,7 +80,7 @@ dotnet_naming_style.pascal_case_style.capitalization = pascal_case
# static fields should have s_ prefix
dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion
dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields
-dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
+dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
dotnet_naming_symbols.static_fields.applicable_kinds = field
dotnet_naming_symbols.static_fields.required_modifiers = static
dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected
@@ -72,7 +90,7 @@ dotnet_naming_style.static_prefix_style.capitalization = camel_case
# internal and private fields should be _camelCase
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
-dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
+dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
@@ -470,7 +488,7 @@ dotnet_diagnostic.SA1200.severity = none
dotnet_diagnostic.SA1201.severity = none
-dotnet_diagnostic.SA1202.severity = error
+dotnet_diagnostic.SA1202.severity = silent
dotnet_diagnostic.SA1203.severity = error
@@ -676,6 +694,9 @@ dotnet_diagnostic.SX1309.severity = error
dotnet_diagnostic.SX1623.severity = none
dotnet_diagnostic.SX1309S.severity=silent
+csharp_style_namespace_declarations = block_scoped:silent
+csharp_style_prefer_method_group_conversion = true:silent
+csharp_style_prefer_top_level_statements = true:silent
# C++ Files
[*.{cpp,h,in}]
diff --git a/src/Directory.build.targets b/src/Directory.build.targets
index 51e7556d3..945cf9815 100644
--- a/src/Directory.build.targets
+++ b/src/Directory.build.targets
@@ -1,30 +1,33 @@
-
- $(AssemblyName) ($(TargetFramework))
-
+
+ $(AssemblyName) ($(TargetFramework))
+
-
- $(DefineConstants);WINDOWS_UWP;P_LINQ
-
+
+ $(DefineConstants);WINDOWS_UWP;P_LINQ
+
-
- $(DefineConstants);P_LINQ;SUPPORTS_BINDINGLIST
-
+
+ $(DefineConstants);P_LINQ;SUPPORTS_BINDINGLIST
+
-
- $(DefineConstants);NETSTANDARD;PORTABLE;P_LINQ;SUPPORTS_BINDINGLIST
-
+
+ $(DefineConstants);NETSTANDARD;PORTABLE;P_LINQ;SUPPORTS_BINDINGLIST
+
-
- $(DefineConstants);NETCOREAPP;P_LINQ;SUPPORTS_BINDINGLIST
-
+
+ $(DefineConstants);NETCOREAPP;P_LINQ;SUPPORTS_BINDINGLIST
+
-
- $(DefineConstants);NETSTANDARD;PORTABLE;P_LINQ;SUPPORTS_BINDINGLIST
-
+
+ $(DefineConstants);NETSTANDARD;PORTABLE;P_LINQ;SUPPORTS_BINDINGLIST
+
-
- $(DefineConstants);NETSTANDARD;PORTABLE;P_LINQ;SUPPORTS_BINDINGLIST
-
+
+ $(DefineConstants);NETSTANDARD;PORTABLE;P_LINQ;SUPPORTS_BINDINGLIST
+
+
+ $(DefineConstants);NETSTANDARD;PORTABLE;P_LINQ;SUPPORTS_BINDINGLIST
+
diff --git a/src/DynamicData.Tests/Binding/BindingLIstBindListFixture.cs b/src/DynamicData.Tests/Binding/BindingLIstBindListFixture.cs
index 86d129d3f..750aaf1ae 100644
--- a/src/DynamicData.Tests/Binding/BindingLIstBindListFixture.cs
+++ b/src/DynamicData.Tests/Binding/BindingLIstBindListFixture.cs
@@ -26,7 +26,10 @@ public BindingLIstBindListFixture()
{
_collection = new BindingList();
_source = new SourceList();
- _binder = _source.Connect().Bind(_collection).Subscribe();
+ _binder = _source.Connect()
+ .AutoRefresh(p => p.Age)
+ .Bind(_collection)
+ .Subscribe();
}
[Fact]
@@ -58,12 +61,29 @@ public void Clear()
_collection.Count.Should().Be(0, "Should be 100 items in the collection");
}
- public void Dispose()
+
+
+ [Fact]
+ public void Refresh()
{
- _binder.Dispose();
- _source.Dispose();
+ var people = _generator.Take(100).ToList();
+ _source.AddRange(people);
+
+ ListChangedEventArgs? args = null;
+
+ _collection.ListChanged += (_, e) =>
+ {
+ args = e;
+ };
+
+ people[10].Age = 100;
+
+ args.Should().NotBeNull();
+ args.ListChangedType.Should().Be(ListChangedType.ItemChanged);
+ args.NewIndex.Should().Be(10);
}
+
[Fact]
public void RemoveSourceRemovesFromTheDestination()
{
@@ -85,6 +105,13 @@ public void UpdateToSourceUpdatesTheDestination()
_collection.Count.Should().Be(1, "Should be 1 item in the collection");
_collection.First().Should().Be(personUpdated, "Should be updated person");
}
+
+ public void Dispose()
+ {
+ _binder.Dispose();
+ _source.Dispose();
+ }
+
}
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/DynamicData.Tests/Binding/BindingListBindCacheFixture.cs b/src/DynamicData.Tests/Binding/BindingListBindCacheFixture.cs
index e45c55516..f76ff68bf 100644
--- a/src/DynamicData.Tests/Binding/BindingListBindCacheFixture.cs
+++ b/src/DynamicData.Tests/Binding/BindingListBindCacheFixture.cs
@@ -57,11 +57,6 @@ public void BatchRemove()
_collection.Count.Should().Be(0, "Should be 100 items in the collection");
}
- public void Dispose()
- {
- _binder.Dispose();
- _source.Dispose();
- }
[Fact]
public void RemoveSourceRemovesFromTheDestination()
@@ -73,6 +68,26 @@ public void RemoveSourceRemovesFromTheDestination()
_collection.Count.Should().Be(0, "Should be 1 item in the collection");
}
+ [Fact]
+ public void Refresh()
+ {
+ var people = _generator.Take(100).ToList();
+ _source.AddOrUpdate(people);
+
+ ListChangedEventArgs? args = null;
+
+ _collection.ListChanged += (_, e) =>
+ {
+ args = e;
+ };
+
+ _source.Refresh(people[10]);
+
+ args.Should().NotBeNull();
+ args.ListChangedType.Should().Be(ListChangedType.ItemChanged);
+ args.NewIndex.Should().Be(10);
+ }
+
[Fact]
public void UpdateToSourceUpdatesTheDestination()
{
@@ -84,6 +99,12 @@ public void UpdateToSourceUpdatesTheDestination()
_collection.Count.Should().Be(1, "Should be 1 item in the collection");
_collection.First().Should().Be(personUpdated, "Should be updated person");
}
+
+ public void Dispose()
+ {
+ _binder.Dispose();
+ _source.Dispose();
+ }
}
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/DynamicData.Tests/Binding/BindingListBindCacheSortedFixture.cs b/src/DynamicData.Tests/Binding/BindingListBindCacheSortedFixture.cs
index db2080220..38fc9c2c1 100644
--- a/src/DynamicData.Tests/Binding/BindingListBindCacheSortedFixture.cs
+++ b/src/DynamicData.Tests/Binding/BindingListBindCacheSortedFixture.cs
@@ -70,11 +70,6 @@ public void CollectionIsInSortOrder()
sorted.Should().BeEquivalentTo(_collection.ToList());
}
- public void Dispose()
- {
- _binder.Dispose();
- _source.Dispose();
- }
[Fact]
public void LargeUpdateInvokesAReset()
@@ -93,6 +88,28 @@ public void LargeUpdateInvokesAReset()
invoked.Should().BeTrue();
}
+ [Fact]
+ public void Refresh()
+ {
+ var people = _generator.Take(100).ToList();
+ _source.AddOrUpdate(people);
+
+ ListChangedEventArgs? args = null;
+
+ _collection.ListChanged += (_, e) =>
+ {
+ args = e;
+ };
+
+ _source.Refresh(people[10]);
+
+ args.Should().NotBeNull();
+ args.ListChangedType.Should().Be(ListChangedType.ItemChanged);
+
+ _collection[args.NewIndex].Should().Be(people[10]);
+ }
+
+
[Fact]
public void RemoveSourceRemovesFromTheDestination()
{
@@ -179,6 +196,15 @@ public void UpdateToSourceUpdatesTheDestination()
_collection.Count.Should().Be(1, "Should be 1 item in the collection");
_collection.First().Should().Be(personUpdated, "Should be updated person");
}
+
+
+ public void Dispose()
+ {
+ _binder.Dispose();
+ _source.Dispose();
+ }
}
+
+
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/DynamicData.Tests/Binding/BindingListToChangeSetFixture.cs b/src/DynamicData.Tests/Binding/BindingListToChangeSetFixture.cs
index d0c9d0638..d1e9ff861 100644
--- a/src/DynamicData.Tests/Binding/BindingListToChangeSetFixture.cs
+++ b/src/DynamicData.Tests/Binding/BindingListToChangeSetFixture.cs
@@ -80,8 +80,12 @@ public void RefreshCausesReplace()
sourceCacheResults.Messages.First().Adds.Should().Be(1);
sourceCacheResults.Messages.Last().Refreshes.Should().Be(1);
- // List receives add and replace instead of refresh
- collectionResults.Messages.Count.Should().Be(2);
+
+ /*
+ List receives add and replace instead of refresh (and as of 23/02/2023 it receives a refresh too!)
+ */
+
+ collectionResults.Messages.Count.Should().Be(3);
collectionResults.Messages.First().Adds.Should().Be(1);
collectionResults.Messages.First().Refreshes.Should().Be(0);
collectionResults.Messages.Last().Replaced.Should().Be(1);
diff --git a/src/DynamicData/Binding/BindingListAdaptor.cs b/src/DynamicData/Binding/BindingListAdaptor.cs
index eb000a74c..2775af261 100644
--- a/src/DynamicData/Binding/BindingListAdaptor.cs
+++ b/src/DynamicData/Binding/BindingListAdaptor.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for full license information.
#if SUPPORTS_BINDINGLIST
-using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
@@ -129,10 +128,18 @@ private static void DoUpdate(IChangeSet changes, BindingList
public static class BindingListEx
{
+ internal static void Clone(this BindingList source, IEnumerable> changes)
+ {
+ // ** Copied from ListEx for binding list specific changes
+ if (source is null) throw new ArgumentNullException(nameof(source));
+ if (changes is null) throw new ArgumentNullException(nameof(changes));
+
+ foreach (var item in changes)
+ {
+ source.Clone(item, EqualityComparer.Default);
+ }
+ }
+
+ private static void Clone(this BindingList source, Change item, IEqualityComparer equalityComparer)
+ {
+ switch (item.Reason)
+ {
+ case ListChangeReason.Add:
+ {
+ var change = item.Item;
+ var hasIndex = change.CurrentIndex >= 0;
+ if (hasIndex)
+ {
+ source.Insert(change.CurrentIndex, change.Current);
+ }
+ else
+ {
+ source.Add(change.Current);
+ }
+
+ break;
+ }
+
+ case ListChangeReason.AddRange:
+ {
+ source.AddOrInsertRange(item.Range, item.Range.Index);
+ break;
+ }
+
+ case ListChangeReason.Clear:
+ {
+ source.ClearOrRemoveMany(item);
+ break;
+ }
+
+ case ListChangeReason.Replace:
+ {
+ var change = item.Item;
+ if (change.CurrentIndex >= 0 && change.CurrentIndex == change.PreviousIndex)
+ {
+ source[change.CurrentIndex] = change.Current;
+ }
+ else
+ {
+ if (change.PreviousIndex == -1)
+ {
+ source.Remove(change.Previous.Value);
+ }
+ else
+ {
+ // is this best? or replace + move?
+ source.RemoveAt(change.PreviousIndex);
+ }
+
+ if (change.CurrentIndex == -1)
+ {
+ source.Add(change.Current);
+ }
+ else
+ {
+ source.Insert(change.CurrentIndex, change.Current);
+ }
+ }
+
+ break;
+ }
+
+ case ListChangeReason.Refresh:
+ {
+ var index = source.IndexOf(item.Item.Current);
+ if (index != -1)
+ source.ResetItem(index);
+ break;
+ }
+
+ case ListChangeReason.Remove:
+ {
+ var change = item.Item;
+ bool hasIndex = change.CurrentIndex >= 0;
+ if (hasIndex)
+ {
+ source.RemoveAt(change.CurrentIndex);
+ }
+ else
+ {
+ int index = source.IndexOf(change.Current, equalityComparer);
+ if (index > -1)
+ {
+ source.RemoveAt(index);
+ }
+ }
+
+ break;
+ }
+
+ case ListChangeReason.RemoveRange:
+ {
+ source.RemoveMany(item.Range);
+ break;
+ }
+
+ case ListChangeReason.Moved:
+ {
+ var change = item.Item;
+ bool hasIndex = change.CurrentIndex >= 0;
+ if (!hasIndex)
+ {
+ throw new UnspecifiedIndexException("Cannot move as an index was not specified");
+ }
+
+ if (source is IExtendedList extendedList)
+ {
+ extendedList.Move(change.PreviousIndex, change.CurrentIndex);
+ }
+ else if (source is ObservableCollection observableCollection)
+ {
+ observableCollection.Move(change.PreviousIndex, change.CurrentIndex);
+ }
+ else
+ {
+ // check this works whatever the index is
+ source.RemoveAt(change.PreviousIndex);
+ source.Insert(change.CurrentIndex, change.Current);
+ }
+
+ break;
+ }
+ }
+ }
+
///
/// Observes list changed args.
///
diff --git a/src/DynamicData/Binding/SortedBindingListAdaptor.cs b/src/DynamicData/Binding/SortedBindingListAdaptor.cs
index 38e194e3a..2e38f479c 100644
--- a/src/DynamicData/Binding/SortedBindingListAdaptor.cs
+++ b/src/DynamicData/Binding/SortedBindingListAdaptor.cs
@@ -4,6 +4,7 @@
#if SUPPORTS_BINDINGLIST
using System;
+using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
@@ -102,10 +103,18 @@ private void DoUpdate(ISortedChangeSet changes)
_list.RemoveAt(change.PreviousIndex);
_list.Insert(change.CurrentIndex, change.Current);
break;
+
+ case ChangeReason.Refresh:
+ {
+ var index = _list.IndexOf(change.Current);
+ if (index != -1)
+ _list.ResetItem(index);
+ break;
+ }
}
}
}
}
}
-#endif
\ No newline at end of file
+#endif
diff --git a/version.json b/version.json
index 35f8c733e..8c9976ef7 100644
--- a/version.json
+++ b/version.json
@@ -1,5 +1,5 @@
{
- "version": "7.12",
+ "version": "7.13",
"publicReleaseRefSpec": [
"^refs/heads/main$", // we release out of master
"^refs/heads/preview/.*", // we release previews