diff --git a/src/Avalonia.Base/AttachedProperty.cs b/src/Avalonia.Base/AttachedProperty.cs
index 4a09f2a80a..27844023ae 100644
--- a/src/Avalonia.Base/AttachedProperty.cs
+++ b/src/Avalonia.Base/AttachedProperty.cs
@@ -13,16 +13,18 @@ namespace Avalonia
///
/// The name of the property.
/// The class that is registering the property.
+ /// The class that the property being is registered on.
/// The property metadata.
/// Whether the property inherits its value.
/// A value validation callback.
public AttachedProperty(
string name,
Type ownerType,
+ Type hostType,
StyledPropertyMetadata metadata,
bool inherits = false,
Func? validate = null)
- : base(name, ownerType, metadata, inherits, validate)
+ : base(name, ownerType, hostType, metadata, inherits, validate)
{
IsAttached = true;
}
diff --git a/src/Avalonia.Base/AvaloniaProperty.cs b/src/Avalonia.Base/AvaloniaProperty.cs
index c57131f7b5..332ca1802c 100644
--- a/src/Avalonia.Base/AvaloniaProperty.cs
+++ b/src/Avalonia.Base/AvaloniaProperty.cs
@@ -39,12 +39,14 @@ namespace Avalonia
/// The name of the property.
/// The type of the property's value.
/// The type of the class that registers the property.
+ /// The class that the property being is registered on.
/// The property metadata.
/// A callback.
protected AvaloniaProperty(
string name,
Type valueType,
Type ownerType,
+ Type hostType,
AvaloniaPropertyMetadata metadata,
Action? notifying = null)
{
@@ -63,9 +65,9 @@ namespace Avalonia
Notifying = notifying;
Id = s_nextId++;
- _metadata.Add(ownerType, metadata ?? throw new ArgumentNullException(nameof(metadata)));
+ _metadata.Add(hostType, metadata ?? throw new ArgumentNullException(nameof(metadata)));
_defaultMetadata = metadata.GenerateTypeSafeMetadata();
- _singleMetadata = new(ownerType, metadata);
+ _singleMetadata = new(hostType, metadata);
}
///
@@ -255,6 +257,7 @@ namespace Avalonia
var result = new StyledProperty(
name,
typeof(TOwner),
+ typeof(TOwner),
metadata,
inherits,
validate);
@@ -301,6 +304,7 @@ namespace Avalonia
var result = new StyledProperty(
name,
typeof(TOwner),
+ typeof(TOwner),
metadata,
inherits,
validate,
@@ -338,7 +342,7 @@ namespace Avalonia
defaultBindingMode: defaultBindingMode,
coerce: coerce);
- var result = new AttachedProperty(name, typeof(TOwner), metadata, inherits, validate);
+ var result = new AttachedProperty(name, typeof(TOwner), typeof(THost), metadata, inherits, validate);
var registry = AvaloniaPropertyRegistry.Instance;
registry.Register(typeof(TOwner), result);
registry.RegisterAttached(typeof(THost), result);
@@ -375,7 +379,7 @@ namespace Avalonia
defaultBindingMode: defaultBindingMode,
coerce: coerce);
- var result = new AttachedProperty(name, ownerType, metadata, inherits, validate);
+ var result = new AttachedProperty(name, ownerType, typeof(THost), metadata, inherits, validate);
var registry = AvaloniaPropertyRegistry.Instance;
registry.Register(ownerType, result);
registry.RegisterAttached(typeof(THost), result);
diff --git a/src/Avalonia.Base/AvaloniaProperty`1.cs b/src/Avalonia.Base/AvaloniaProperty`1.cs
index f8c062a176..f08c0e0a02 100644
--- a/src/Avalonia.Base/AvaloniaProperty`1.cs
+++ b/src/Avalonia.Base/AvaloniaProperty`1.cs
@@ -19,14 +19,16 @@ namespace Avalonia
///
/// The name of the property.
/// The type of the class that registers the property.
+ /// The class that the property being is registered on.
/// The property metadata.
/// A callback.
protected AvaloniaProperty(
string name,
Type ownerType,
+ Type hostType,
AvaloniaPropertyMetadata metadata,
Action? notifying = null)
- : base(name, typeof(TValue), ownerType, metadata, notifying)
+ : base(name, typeof(TValue), ownerType, hostType, metadata, notifying)
{
_changed = new LightweightSubject>();
}
diff --git a/src/Avalonia.Base/DirectPropertyBase.cs b/src/Avalonia.Base/DirectPropertyBase.cs
index 7e5a962157..94694e6209 100644
--- a/src/Avalonia.Base/DirectPropertyBase.cs
+++ b/src/Avalonia.Base/DirectPropertyBase.cs
@@ -24,7 +24,7 @@ namespace Avalonia
string name,
Type ownerType,
AvaloniaPropertyMetadata metadata)
- : base(name, ownerType, metadata)
+ : base(name, ownerType, ownerType, metadata)
{
Owner = ownerType;
}
diff --git a/src/Avalonia.Base/StyledProperty.cs b/src/Avalonia.Base/StyledProperty.cs
index 5cb330eda9..76ba83b88d 100644
--- a/src/Avalonia.Base/StyledProperty.cs
+++ b/src/Avalonia.Base/StyledProperty.cs
@@ -16,6 +16,7 @@ namespace Avalonia
///
/// The name of the property.
/// The type of the class that registers the property.
+ /// The class that the property being is registered on.
/// The property metadata.
/// Whether the property inherits its value.
///
@@ -26,11 +27,12 @@ namespace Avalonia
public StyledProperty(
string name,
Type ownerType,
+ Type hostType,
StyledPropertyMetadata metadata,
bool inherits = false,
Func? validate = null,
Action? notifying = null)
- : base(name, ownerType, metadata, notifying)
+ : base(name, ownerType, hostType, metadata, notifying)
{
Inherits = inherits;
ValidateValue = validate;
diff --git a/tests/Avalonia.Base.UnitTests/AttachedPropertyTests.cs b/tests/Avalonia.Base.UnitTests/AttachedPropertyTests.cs
index f461240d68..8a6e7b8679 100644
--- a/tests/Avalonia.Base.UnitTests/AttachedPropertyTests.cs
+++ b/tests/Avalonia.Base.UnitTests/AttachedPropertyTests.cs
@@ -1,3 +1,4 @@
+using Avalonia.Controls;
using Xunit;
namespace Avalonia.Base.UnitTests
@@ -10,6 +11,7 @@ namespace Avalonia.Base.UnitTests
var property = new AttachedProperty(
"Foo",
typeof(Class1),
+ typeof(Control),
new StyledPropertyMetadata());
Assert.True(property.IsAttached);
diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Coercion.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Coercion.cs
index fe4262331f..0d0456dbda 100644
--- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Coercion.cs
+++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Coercion.cs
@@ -31,6 +31,16 @@ namespace Avalonia.Base.UnitTests
Assert.Equal(100, target.GetValue(Class1.AttachedProperty));
}
+ [Fact]
+ public void Coerces_Set_Value_Attached_On_Class_Not_Derived_From_Owner()
+ {
+ var target = new Class2();
+
+ target.SetValue(Class1.AttachedProperty, 150);
+
+ Assert.Equal(100, target.GetValue(Class1.AttachedProperty));
+ }
+
[Fact]
public void Coerces_Bound_Value()
{
@@ -301,7 +311,7 @@ namespace Avalonia.Base.UnitTests
coerce: CoerceFoo);
public static readonly AttachedProperty AttachedProperty =
- AvaloniaProperty.RegisterAttached(
+ AvaloniaProperty.RegisterAttached(
"Attached",
defaultValue: 11,
coerce: CoerceFoo);
@@ -332,8 +342,9 @@ namespace Avalonia.Base.UnitTests
public static int CoerceFoo(AvaloniaObject instance, int value)
{
- var o = (Class1)instance;
- return Math.Clamp(value, o.MinFoo, o.MaxFoo);
+ return instance is Class1 o ?
+ Math.Clamp(value, o.MinFoo, o.MaxFoo) :
+ Math.Clamp(value, 0, 100);
}
protected override void OnPropertyChangedCore(AvaloniaPropertyChangedEventArgs change)
diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Validation.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Validation.cs
index 513aeb65ab..2b3bd07fed 100644
--- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Validation.cs
+++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Validation.cs
@@ -15,6 +15,7 @@ namespace Avalonia.Base.UnitTests
new StyledProperty(
"BadDefault",
typeof(Class1),
+ typeof(Class1),
new StyledPropertyMetadata(101),
validate: Class1.ValidateFoo));
}
diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaPropertyRegistryTests.cs b/tests/Avalonia.Base.UnitTests/AvaloniaPropertyRegistryTests.cs
index 0d62f20f7e..23e21c1645 100644
--- a/tests/Avalonia.Base.UnitTests/AvaloniaPropertyRegistryTests.cs
+++ b/tests/Avalonia.Base.UnitTests/AvaloniaPropertyRegistryTests.cs
@@ -22,7 +22,7 @@ namespace Avalonia.Base.UnitTests
{
var registry = new AvaloniaPropertyRegistry();
var metadata = new StyledPropertyMetadata();
- var property = new AttachedProperty("test", typeof(object), metadata, true);
+ var property = new AttachedProperty("test", typeof(object), typeof(object), metadata, true);
registry.Register(typeof(object), property);
registry.RegisterAttached(typeof(AvaloniaPropertyRegistryTests), property);
property.AddOwner();
diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs b/tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs
index e44c15d962..d974351b1e 100644
--- a/tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs
+++ b/tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs
@@ -157,7 +157,7 @@ namespace Avalonia.Base.UnitTests
private class TestProperty : AvaloniaProperty
{
public TestProperty(string name, Type ownerType, TestMetadata metadata = null)
- : base(name, ownerType, metadata ?? new TestMetadata())
+ : base(name, ownerType, ownerType, metadata ?? new TestMetadata())
{
}
diff --git a/tests/Avalonia.Base.UnitTests/StyledPropertyTests.cs b/tests/Avalonia.Base.UnitTests/StyledPropertyTests.cs
index f0aa47784d..5304c74c39 100644
--- a/tests/Avalonia.Base.UnitTests/StyledPropertyTests.cs
+++ b/tests/Avalonia.Base.UnitTests/StyledPropertyTests.cs
@@ -9,7 +9,8 @@ namespace Avalonia.Base.UnitTests
{
var p1 = new StyledProperty(
"p1",
- typeof(Class1),
+ typeof(Class1),
+ typeof(Class1),
new StyledPropertyMetadata());
var p2 = p1.AddOwner();
@@ -24,6 +25,7 @@ namespace Avalonia.Base.UnitTests
var p1 = new StyledProperty(
"p1",
typeof(Class1),
+ typeof(Class1),
new StyledPropertyMetadata());
var p2 = p1.AddOwner();
diff --git a/tests/Avalonia.Base.UnitTests/Utilities/AvaloniaPropertyDictionaryTests.cs b/tests/Avalonia.Base.UnitTests/Utilities/AvaloniaPropertyDictionaryTests.cs
index 362eee8035..4b4aeb4344 100644
--- a/tests/Avalonia.Base.UnitTests/Utilities/AvaloniaPropertyDictionaryTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Utilities/AvaloniaPropertyDictionaryTests.cs
@@ -18,6 +18,7 @@ namespace Avalonia.Base.UnitTests.Utilities
TestProperties[i] = new StyledProperty(
$"Test{i}",
typeof(AvaloniaPropertyDictionaryTests),
+ typeof(AvaloniaPropertyDictionaryTests),
new StyledPropertyMetadata());
}
diff --git a/tests/Avalonia.Benchmarks/Utilities/AvaloniaPropertyDictionaryBenchmarks.cs b/tests/Avalonia.Benchmarks/Utilities/AvaloniaPropertyDictionaryBenchmarks.cs
index e160c8dfa8..ef21100d1f 100644
--- a/tests/Avalonia.Benchmarks/Utilities/AvaloniaPropertyDictionaryBenchmarks.cs
+++ b/tests/Avalonia.Benchmarks/Utilities/AvaloniaPropertyDictionaryBenchmarks.cs
@@ -172,7 +172,7 @@ internal sealed class AvaloniaPropertyValueStoreOld
internal class MockProperty : StyledProperty
{
- public MockProperty(string name) : base(name, typeof(object), new StyledPropertyMetadata())
+ public MockProperty(string name) : base(name, typeof(object), typeof(object), new StyledPropertyMetadata())
{
}
}