Skip to content

Commit 0fb704d

Browse files
authored
Merge pull request #250 from CommunityToolkit/dev/display-attribute-breaking-broadcast
Fix [AlsoBroadcastChange] not working when followed by other attributes
2 parents 73e85b4 + 612a6ea commit 0fb704d

File tree

2 files changed

+60
-7
lines changed

2 files changed

+60
-7
lines changed

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservablePropertyGenerator.Execute.cs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,19 @@ internal static class Execute
9191
{
9292
// Gather dependent property and command names
9393
if (TryGatherDependentPropertyChangedNames(fieldSymbol, attributeData, propertyChangedNames, builder) ||
94-
TryGatherDependentCommandNames(fieldSymbol, attributeData, notifiedCommandNames, builder) ||
95-
TryGetIsBroadcastingChanges(fieldSymbol, attributeData, builder, out alsoBroadcastChange))
94+
TryGatherDependentCommandNames(fieldSymbol, attributeData, notifiedCommandNames, builder))
9695
{
9796
continue;
9897
}
9998

99+
// Check whether the property should also broadcast changes
100+
if (TryGetIsBroadcastingChanges(fieldSymbol, attributeData, builder, out bool isBroadcastTargetValid))
101+
{
102+
alsoBroadcastChange = isBroadcastTargetValid;
103+
104+
continue;
105+
}
106+
100107
// Track the current validation attribute, if applicable
101108
if (attributeData.AttributeClass?.InheritsFromFullyQualifiedName("global::System.ComponentModel.DataAnnotations.ValidationAttribute") == true)
102109
{
@@ -332,21 +339,21 @@ bool IsCommandNameValidWithGeneratedMembers(string commandName)
332339
/// <param name="fieldSymbol">The input <see cref="IFieldSymbol"/> instance to process.</param>
333340
/// <param name="attributeData">The <see cref="AttributeData"/> instance for <paramref name="fieldSymbol"/>.</param>
334341
/// <param name="diagnostics">The current collection of gathered diagnostics.</param>
335-
/// <param name="alsoBroadcastChange">Whether or not the resulting property should also broadcast changes.</param>
342+
/// <param name="isBroadcastTargetValid">Whether or not the the property is in a valid target that can broadcast changes.</param>
336343
/// <returns>Whether or not the generated property for <paramref name="fieldSymbol"/> used <c>[AlsoBroadcastChange]</c>.</returns>
337344
private static bool TryGetIsBroadcastingChanges(
338345
IFieldSymbol fieldSymbol,
339346
AttributeData attributeData,
340347
ImmutableArray<Diagnostic>.Builder diagnostics,
341-
out bool alsoBroadcastChange)
348+
out bool isBroadcastTargetValid)
342349
{
343350
if (attributeData.AttributeClass?.HasFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.AlsoBroadcastChangeAttribute") == true)
344351
{
345352
// If the containing type is valid, track it
346353
if (fieldSymbol.ContainingType.InheritsFromFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.ObservableRecipient") ||
347354
fieldSymbol.ContainingType.HasOrInheritsAttributeWithFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.ObservableRecipientAttribute"))
348355
{
349-
alsoBroadcastChange = true;
356+
isBroadcastTargetValid = true;
350357

351358
return true;
352359
}
@@ -358,12 +365,12 @@ private static bool TryGetIsBroadcastingChanges(
358365
fieldSymbol.ContainingType,
359366
fieldSymbol.Name);
360367

361-
alsoBroadcastChange = false;
368+
isBroadcastTargetValid = false;
362369

363370
return true;
364371
}
365372

366-
alsoBroadcastChange = false;
373+
isBroadcastTargetValid = false;
367374

368375
return false;
369376
}

tests/CommunityToolkit.Mvvm.UnitTests/Test_ObservablePropertyAttribute.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,43 @@ public void Test_ObservableProperty_ModelWithCultureAwarePropertyName()
608608
CollectionAssert.AreEqual(new[] { nameof(model.InputFolder) }, propertyNames);
609609
}
610610

611+
// See https://github.com/CommunityToolkit/dotnet/issues/242
612+
[TestMethod]
613+
public void Test_ObservableProperty_ModelWithAlsoBroadcastChangeAndDisplayAttributeLast()
614+
{
615+
IMessenger messenger = new StrongReferenceMessenger();
616+
ModelWithAlsoBroadcastChangeAndDisplayAttributeLast model = new(messenger);
617+
618+
List<string?> propertyNames = new();
619+
620+
model.PropertyChanged += (s, e) => propertyNames.Add(e.PropertyName);
621+
622+
object newValue = new();
623+
bool isMessageReceived = false;
624+
625+
messenger.Register<Test_ObservablePropertyAttribute, PropertyChangedMessage<object>>(this, (r, m) =>
626+
{
627+
if (m.Sender != model)
628+
{
629+
Assert.Fail();
630+
}
631+
632+
if (m.NewValue != newValue)
633+
{
634+
Assert.Fail();
635+
}
636+
637+
isMessageReceived = true;
638+
});
639+
640+
model.SomeProperty = newValue;
641+
642+
Assert.AreEqual(model.SomeProperty, newValue);
643+
Assert.IsTrue(isMessageReceived);
644+
645+
CollectionAssert.AreEqual(new[] { nameof(model.SomeProperty) }, propertyNames);
646+
}
647+
611648
public abstract partial class BaseViewModel : ObservableObject
612649
{
613650
public string? Content { get; set; }
@@ -991,4 +1028,13 @@ partial class ModelWithCultureAwarePropertyName
9911028
[ObservableProperty]
9921029
private int _inputFolder;
9931030
}
1031+
1032+
[ObservableRecipient]
1033+
public sealed partial class ModelWithAlsoBroadcastChangeAndDisplayAttributeLast : ObservableValidator
1034+
{
1035+
[ObservableProperty]
1036+
[AlsoBroadcastChange]
1037+
[Display(Name = "Foo bar baz")]
1038+
private object? _someProperty;
1039+
}
9941040
}

0 commit comments

Comments
 (0)