diff --git a/src/Markup/Perspex.Markup.Xaml/Context/PerspexAttachableXamlMember.cs b/src/Markup/Perspex.Markup.Xaml/Context/PerspexAttachableXamlMember.cs
new file mode 100644
index 0000000000..117f7768f1
--- /dev/null
+++ b/src/Markup/Perspex.Markup.Xaml/Context/PerspexAttachableXamlMember.cs
@@ -0,0 +1,33 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using Perspex.Markup.Xaml.Binding;
+using OmniXaml;
+using OmniXaml.Typing;
+using System.Reflection;
+
+namespace Perspex.Markup.Xaml.Context
+{
+ public class PerspexAttachableXamlMember : AttachableXamlMember
+ {
+ public PerspexAttachableXamlMember(string name,
+ XamlType owner,
+ MethodInfo getter,
+ MethodInfo setter,
+ IXamlTypeRepository xamlTypeRepository,
+ ITypeFeatureProvider featureProvider)
+ : base(name, getter, setter, xamlTypeRepository, featureProvider)
+ {
+ }
+
+ protected override IXamlMemberValuePlugin LookupXamlMemberValueConnector()
+ {
+ return new PerspexXamlMemberValuePlugin(this);
+ }
+
+ public override string ToString()
+ {
+ return "Perspex Attachable XAML Member " + base.ToString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlMemberValuePlugin.cs b/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlMemberValuePlugin.cs
index fd7a786649..36e1d03ea8 100644
--- a/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlMemberValuePlugin.cs
+++ b/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlMemberValuePlugin.cs
@@ -5,6 +5,7 @@ using System;
using System.Linq;
using System.Reactive.Linq;
using System.Reflection;
+using System.Runtime.CompilerServices;
using Glass;
using OmniXaml.ObjectAssembler;
using OmniXaml.Typing;
@@ -16,9 +17,9 @@ namespace Perspex.Markup.Xaml.Context
{
public class PerspexXamlMemberValuePlugin : MemberValuePlugin
{
- private readonly XamlMember _xamlMember;
+ private readonly MutableXamlMember _xamlMember;
- public PerspexXamlMemberValuePlugin(XamlMember xamlMember)
+ public PerspexXamlMemberValuePlugin(MutableXamlMember xamlMember)
: base(xamlMember)
{
_xamlMember = xamlMember;
@@ -73,6 +74,7 @@ namespace Perspex.Markup.Xaml.Context
else
{
var perspexObject = instance as PerspexObject;
+ var attached = _xamlMember as PerspexAttachableXamlMember;
if (perspexObject == null)
{
@@ -80,13 +82,31 @@ namespace Perspex.Markup.Xaml.Context
$"Cannot bind to an object of type '{instance.GetType()}");
}
- var property = perspexObject.GetRegisteredProperties()
- .FirstOrDefault(x => x.Name == _xamlMember.Name);
+ PerspexProperty property;
+ string propertyName;
+
+ if (attached == null)
+ {
+ propertyName = _xamlMember.Name;
+ property = perspexObject.GetRegisteredProperties()
+ .FirstOrDefault(x => x.Name == propertyName);
+ }
+ else
+ {
+ // Ensure the OwnerType's static ctor has been run.
+ RuntimeHelpers.RunClassConstructor(attached.DeclaringType.UnderlyingType.TypeHandle);
+
+ propertyName = attached.DeclaringType.UnderlyingType.Name + '.' + _xamlMember.Name;
+
+ property = perspexObject.GetRegisteredProperties()
+ .Where(x => x.IsAttached && x.OwnerType == attached.DeclaringType.UnderlyingType)
+ .FirstOrDefault(x => x.Name == _xamlMember.Name);
+ }
if (property == null)
{
throw new InvalidOperationException(
- $"Cannot find '{_xamlMember.Name}' on '{instance.GetType()}");
+ $"Cannot find '{propertyName}' on '{instance.GetType()}");
}
var binding = new XamlBinding
diff --git a/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlType.cs b/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlType.cs
index 0d1fb218b1..dc6b7398f4 100644
--- a/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlType.cs
+++ b/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlType.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
+using System.Reflection;
using OmniXaml;
using OmniXaml.Typing;
using Perspex.Markup.Xaml.Binding;
@@ -22,6 +23,14 @@ namespace Perspex.Markup.Xaml.Context
return new PerspexXamlMember(name, this, TypeRepository, FeatureProvider);
}
+ protected override AttachableXamlMember LookupAttachableMember(string name)
+ {
+ // OmniXAML seems to require a getter and setter even though we don't use them.
+ var getter = UnderlyingType.GetTypeInfo().GetDeclaredMethod("Get" + name);
+ var setter = UnderlyingType.GetTypeInfo().GetDeclaredMethod("Set" + name);
+ return new PerspexAttachableXamlMember(name, this, getter, setter, TypeRepository, FeatureProvider);
+ }
+
public override string ToString()
{
return "Perspex XAML Type " + base.ToString();
diff --git a/src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj b/src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj
index 987b630907..d34c97c50f 100644
--- a/src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj
+++ b/src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj
@@ -42,6 +42,7 @@
+