Browse Source

Get the PerspexProperty type from the Style.

pull/297/head
Steven Kirk 11 years ago
parent
commit
526ce1e0cc
  1. 20
      samples/XamlTestApplicationPcl/XamlTestApp.paml
  2. 62
      src/Markup/Perspex.Markup.Xaml/Converters/PerspexPropertyTypeConverter.cs
  3. 45
      tests/Perspex.Markup.Xaml.UnitTests/Converters/PerspexPropertyConverterTest.cs

20
samples/XamlTestApplicationPcl/XamlTestApp.paml

@ -3,13 +3,13 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Styles>
<Style Selector="Button">
<Setter Property="Button.Background" Value="#ffaaaaaa"/>
<Setter Property="Button.BorderBrush" Value="#ffaaaaaa"/>
<Setter Property="Button.BorderThickness" Value="2"/>
<Setter Property="Button.Foreground" Value="Black"/>
<Setter Property="Button.HorizontalContentAlignment" Value="Center"/>
<Setter Property="Button.VerticalContentAlignment" Value="Center"/>
<Setter Property="Button.Template">
<Setter Property="Background" Value="#ffaaaaaa"/>
<Setter Property="BorderBrush" Value="#ffaaaaaa"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<ControlTemplate TargetType="Button">
<Border Padding="3"
Background="{TemplateBinding Background}"
@ -24,13 +24,13 @@
</Setter>
</Style>
<Style Selector="Button:pointerover">
<Setter Property="Button.BorderBrush" Value="#ff888888"/>
<Setter Property="BorderBrush" Value="#ff888888"/>
</Style>
<Style Selector="Button:pressed">
<Setter Property="Button.Background" Value="#ff888888"/>
<Setter Property="Background" Value="#ff888888"/>
</Style>
<Style Selector="Button:disabled">
<Setter Property="Button.Opacity" Value="0.5"/>
<Setter Property="Opacity" Value="0.5"/>
</Style>
</Application.Styles>
</Application>

62
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}'.");
}
}
}
}

45
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<Class1>());
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<IXamlTypeConverterContext>();
var topDownValueContext = new Mock<ITopDownValueContext>();
var typeRepository = new Mock<IXamlTypeRepository>();
var featureProvider = new Mock<ITypeFeatureProvider>();
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<XamlType>())).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<string> FooProperty =
PerspexProperty.Register<Class1, string>("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

Loading…
Cancel
Save