diff --git a/samples/XamlTestApplicationPcl/XamlTestApp.paml b/samples/XamlTestApplicationPcl/XamlTestApp.paml
index 532199aab9..8a4a317394 100644
--- a/samples/XamlTestApplicationPcl/XamlTestApp.paml
+++ b/samples/XamlTestApplicationPcl/XamlTestApp.paml
@@ -3,13 +3,13 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
\ No newline at end of file
diff --git a/src/Markup/Perspex.Markup.Xaml/Converters/PerspexPropertyTypeConverter.cs b/src/Markup/Perspex.Markup.Xaml/Converters/PerspexPropertyTypeConverter.cs
index 1cdc3cc4f1..b46364d4c4 100644
--- a/src/Markup/Perspex.Markup.Xaml/Converters/PerspexPropertyTypeConverter.cs
+++ b/src/Markup/Perspex.Markup.Xaml/Converters/PerspexPropertyTypeConverter.cs
@@ -25,30 +25,38 @@ namespace Perspex.Markup.Xaml.Converters
public object ConvertFrom(IXamlTypeConverterContext context, CultureInfo culture, object value)
{
var s = (string)value;
- var lastDot = s.LastIndexOf('.');
- if (lastDot == -1)
- {
- throw new NotSupportedException("PerspexProperties must currently be fully qualified.");
- }
+ string typeName;
+ string propertyName;
+ Type type;
- var typeName = s.Substring(0, lastDot);
- var propertyName = s.Substring(lastDot + 1);
- var type = context.TypeRepository.GetByQualifiedName(typeName)?.UnderlyingType;
- var styleType = context.TypeRepository.GetXamlType(typeof(Style));
+ ParseProperty(s, out typeName, out propertyName);
- // ATTN: SuperJMN
- //var style = ((XamlTypeConverterContext)context).TopDownValueContext.GetLastInstance(styleType);
+ if (typeName == null)
+ {
+ var styleType = context.TypeRepository.GetXamlType(typeof(Style));
+ var style = (Style)context.TopDownValueContext.GetLastInstance(styleType);
+ type = style.Selector.TargetType;
- if (type == null)
+ if (type == null)
+ {
+ throw new XamlParseException(
+ "Could not determine the target type. Please fully qualify the property name.");
+ }
+ }
+ else
{
- throw new XamlParseException($"Could not find type '{typeName}'.");
+ type = context.TypeRepository.GetByQualifiedName(typeName)?.UnderlyingType;
+
+ if (type == null)
+ {
+ throw new XamlParseException($"Could not find type '{typeName}'.");
+ }
}
// First look for non-attached property on the type and then look for an attached property.
- var property = PerspexPropertyRegistry.Instance.GetRegistered(type)
- .FirstOrDefault(x => x.Name == propertyName);
-
+ var property = PerspexPropertyRegistry.Instance.FindRegistered(type, s);
+
if (property == null)
{
property = PerspexPropertyRegistry.Instance.GetAttached(type)
@@ -58,7 +66,7 @@ namespace Perspex.Markup.Xaml.Converters
if (property == null)
{
throw new XamlParseException(
- $"Could not find PerspexProperty '{typeName}'.{propertyName}.");
+ $"Could not find PerspexProperty '{type.Name}.{propertyName}'.");
}
return property;
@@ -68,5 +76,25 @@ namespace Perspex.Markup.Xaml.Converters
{
throw new NotImplementedException();
}
+
+ private void ParseProperty(string s, out string typeName, out string propertyName)
+ {
+ var split = s.Split('.');
+
+ if (split.Length == 1)
+ {
+ typeName = null;
+ propertyName = split[0];
+ }
+ else if (split.Length == 2)
+ {
+ typeName = split[0];
+ propertyName = split[1];
+ }
+ else
+ {
+ throw new XamlParseException($"Invalid property name: '{s}'.");
+ }
+ }
}
}
\ No newline at end of file
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/Converters/PerspexPropertyConverterTest.cs b/tests/Perspex.Markup.Xaml.UnitTests/Converters/PerspexPropertyConverterTest.cs
index ebf192679a..9b6230df17 100644
--- a/tests/Perspex.Markup.Xaml.UnitTests/Converters/PerspexPropertyConverterTest.cs
+++ b/tests/Perspex.Markup.Xaml.UnitTests/Converters/PerspexPropertyConverterTest.cs
@@ -1,11 +1,14 @@
// 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 System;
using Moq;
using OmniXaml;
+using OmniXaml.ObjectAssembler.Commands;
using OmniXaml.TypeConversion;
using OmniXaml.Typing;
using Perspex.Markup.Xaml.Converters;
+using Perspex.Styling;
using Xunit;
namespace Perspex.Markup.Xaml.UnitTests.Converters
@@ -25,6 +28,19 @@ namespace Perspex.Markup.Xaml.UnitTests.Converters
var target = new PerspexPropertyTypeConverter();
var context = CreateContext();
var result = target.ConvertFrom(context, null, "Class1.Foo");
+
+ Assert.Equal(Class1.FooProperty, result);
+ }
+
+ [Fact]
+ public void ConvertFrom_Uses_Selector_TargetType()
+ {
+ var target = new PerspexPropertyTypeConverter();
+ var style = new Style(x => x.OfType());
+ var context = CreateContext(style);
+ var result = target.ConvertFrom(context, null, "Foo");
+
+ Assert.Equal(Class1.FooProperty, result);
}
[Fact]
@@ -33,25 +49,50 @@ namespace Perspex.Markup.Xaml.UnitTests.Converters
var target = new PerspexPropertyTypeConverter();
var context = CreateContext();
var result = target.ConvertFrom(context, null, "AttachedOwner.Attached");
+
+ Assert.Equal(AttachedOwner.AttachedProperty, result);
}
- private IXamlTypeConverterContext CreateContext()
+ private IXamlTypeConverterContext CreateContext(Style style = null)
{
var context = new Mock();
+ var topDownValueContext = new Mock();
var typeRepository = new Mock();
var featureProvider = new Mock();
var class1XamlType = new XamlType(typeof(Class1), typeRepository.Object, null, featureProvider.Object);
var attachedOwnerXamlType = new XamlType(typeof(AttachedOwner), typeRepository.Object, null, featureProvider.Object);
+ context.Setup(x => x.TopDownValueContext).Returns(topDownValueContext.Object);
context.Setup(x => x.TypeRepository).Returns(typeRepository.Object);
+ topDownValueContext.Setup(x => x.GetLastInstance(It.IsAny())).Returns(style);
typeRepository.Setup(x => x.GetByQualifiedName("Class1")).Returns(class1XamlType);
typeRepository.Setup(x => x.GetByQualifiedName("AttachedOwner")).Returns(attachedOwnerXamlType);
return context.Object;
}
- private class Class1 : PerspexObject
+ private class Class1 : PerspexObject, IStyleable
{
public static readonly PerspexProperty FooProperty =
PerspexProperty.Register("Foo");
+
+ public Classes Classes
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public string Name
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public Type StyleKey
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public ITemplatedControl TemplatedParent
+ {
+ get { throw new NotImplementedException(); }
+ }
}
private class AttachedOwner