diff --git a/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservablePropertyGenerator.Execute.cs b/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservablePropertyGenerator.Execute.cs
index efac4276..0e99c852 100644
--- a/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservablePropertyGenerator.Execute.cs
+++ b/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservablePropertyGenerator.Execute.cs
@@ -91,12 +91,19 @@ internal static class Execute
{
// Gather dependent property and command names
if (TryGatherDependentPropertyChangedNames(fieldSymbol, attributeData, propertyChangedNames, builder) ||
- TryGatherDependentCommandNames(fieldSymbol, attributeData, notifiedCommandNames, builder) ||
- TryGetIsBroadcastingChanges(fieldSymbol, attributeData, builder, out alsoBroadcastChange))
+ TryGatherDependentCommandNames(fieldSymbol, attributeData, notifiedCommandNames, builder))
{
continue;
}
+ // Check whether the property should also broadcast changes
+ if (TryGetIsBroadcastingChanges(fieldSymbol, attributeData, builder, out bool isBroadcastTargetValid))
+ {
+ alsoBroadcastChange = isBroadcastTargetValid;
+
+ continue;
+ }
+
// Track the current validation attribute, if applicable
if (attributeData.AttributeClass?.InheritsFromFullyQualifiedName("global::System.ComponentModel.DataAnnotations.ValidationAttribute") == true)
{
@@ -332,13 +339,13 @@ bool IsCommandNameValidWithGeneratedMembers(string commandName)
/// The input instance to process.
/// The instance for .
/// The current collection of gathered diagnostics.
- /// Whether or not the resulting property should also broadcast changes.
+ /// Whether or not the the property is in a valid target that can broadcast changes.
/// Whether or not the generated property for used [AlsoBroadcastChange].
private static bool TryGetIsBroadcastingChanges(
IFieldSymbol fieldSymbol,
AttributeData attributeData,
ImmutableArray.Builder diagnostics,
- out bool alsoBroadcastChange)
+ out bool isBroadcastTargetValid)
{
if (attributeData.AttributeClass?.HasFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.AlsoBroadcastChangeAttribute") == true)
{
@@ -346,7 +353,7 @@ private static bool TryGetIsBroadcastingChanges(
if (fieldSymbol.ContainingType.InheritsFromFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.ObservableRecipient") ||
fieldSymbol.ContainingType.HasOrInheritsAttributeWithFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.ObservableRecipientAttribute"))
{
- alsoBroadcastChange = true;
+ isBroadcastTargetValid = true;
return true;
}
@@ -358,12 +365,12 @@ private static bool TryGetIsBroadcastingChanges(
fieldSymbol.ContainingType,
fieldSymbol.Name);
- alsoBroadcastChange = false;
+ isBroadcastTargetValid = false;
return true;
}
- alsoBroadcastChange = false;
+ isBroadcastTargetValid = false;
return false;
}
diff --git a/tests/CommunityToolkit.Mvvm.UnitTests/Test_ObservablePropertyAttribute.cs b/tests/CommunityToolkit.Mvvm.UnitTests/Test_ObservablePropertyAttribute.cs
index ec7d1a93..ea0db7b4 100644
--- a/tests/CommunityToolkit.Mvvm.UnitTests/Test_ObservablePropertyAttribute.cs
+++ b/tests/CommunityToolkit.Mvvm.UnitTests/Test_ObservablePropertyAttribute.cs
@@ -608,6 +608,43 @@ public void Test_ObservableProperty_ModelWithCultureAwarePropertyName()
CollectionAssert.AreEqual(new[] { nameof(model.InputFolder) }, propertyNames);
}
+ // See https://github.com/CommunityToolkit/dotnet/issues/242
+ [TestMethod]
+ public void Test_ObservableProperty_ModelWithAlsoBroadcastChangeAndDisplayAttributeLast()
+ {
+ IMessenger messenger = new StrongReferenceMessenger();
+ ModelWithAlsoBroadcastChangeAndDisplayAttributeLast model = new(messenger);
+
+ List propertyNames = new();
+
+ model.PropertyChanged += (s, e) => propertyNames.Add(e.PropertyName);
+
+ object newValue = new();
+ bool isMessageReceived = false;
+
+ messenger.Register>(this, (r, m) =>
+ {
+ if (m.Sender != model)
+ {
+ Assert.Fail();
+ }
+
+ if (m.NewValue != newValue)
+ {
+ Assert.Fail();
+ }
+
+ isMessageReceived = true;
+ });
+
+ model.SomeProperty = newValue;
+
+ Assert.AreEqual(model.SomeProperty, newValue);
+ Assert.IsTrue(isMessageReceived);
+
+ CollectionAssert.AreEqual(new[] { nameof(model.SomeProperty) }, propertyNames);
+ }
+
public abstract partial class BaseViewModel : ObservableObject
{
public string? Content { get; set; }
@@ -991,4 +1028,13 @@ partial class ModelWithCultureAwarePropertyName
[ObservableProperty]
private int _inputFolder;
}
+
+ [ObservableRecipient]
+ public sealed partial class ModelWithAlsoBroadcastChangeAndDisplayAttributeLast : ObservableValidator
+ {
+ [ObservableProperty]
+ [AlsoBroadcastChange]
+ [Display(Name = "Foo bar baz")]
+ private object? _someProperty;
+ }
}