Browse Source

Return BindingError from property plugins.

pull/494/merge
Steven Kirk 11 years ago
parent
commit
6a5208621e
  1. 4
      src/Markup/Perspex.Markup/Data/ExpressionSubject.cs
  2. 2
      src/Markup/Perspex.Markup/Data/Plugins/IPropertyAccessorPlugin.cs
  3. 13
      src/Markup/Perspex.Markup/Data/Plugins/InpcPropertyAccessorPlugin.cs
  4. 14
      src/Markup/Perspex.Markup/Data/Plugins/PerspexPropertyAccessorPlugin.cs
  5. 39
      src/Markup/Perspex.Markup/Data/Plugins/PropertyError.cs
  6. 2
      src/Markup/Perspex.Markup/Data/PropertyAccessorNode.cs
  7. 2
      src/Markup/Perspex.Markup/DefaultValueConverter.cs
  8. 1
      src/Markup/Perspex.Markup/Perspex.Markup.csproj
  9. 14
      tests/Perspex.Markup.UnitTests/Data/ExpressionObserverTests_Property.cs

4
src/Markup/Perspex.Markup/Data/ExpressionSubject.cs

@ -153,7 +153,9 @@ namespace Perspex.Markup.Data
private object ConvertValue(object value)
{
var converted = Converter.Convert(
var converted =
value as BindingError ??
Converter.Convert(
value,
_targetType,
ConverterParameter,

2
src/Markup/Perspex.Markup/Data/Plugins/IPropertyAccessorPlugin.cs

@ -26,7 +26,7 @@ namespace Perspex.Markup.Data.Plugins
/// <param name="changed">A function to call when the property changes.</param>
/// <returns>
/// An <see cref="IPropertyAccessor"/> interface through which future interactions with the
/// property will be made, or null if the property was not found.
/// property will be made.
/// </returns>
IPropertyAccessor Start(
WeakReference reference,

13
src/Markup/Perspex.Markup/Data/Plugins/InpcPropertyAccessorPlugin.cs

@ -38,7 +38,7 @@ namespace Perspex.Markup.Data.Plugins
/// <param name="changed">A function to call when the property changes.</param>
/// <returns>
/// An <see cref="IPropertyAccessor"/> interface through which future interactions with the
/// property will be made, or null if the property was not found.
/// property will be made.
/// </returns>
public IPropertyAccessor Start(
WeakReference reference,
@ -58,14 +58,9 @@ namespace Perspex.Markup.Data.Plugins
}
else
{
Logger.Error(
LogArea.Binding,
this,
"Could not find CLR property {Property} on {Source}",
propertyName,
instance);
return null;
var message = $"Could not find CLR property '{propertyName}' on '{instance}'";
var exception = new MissingMemberException(message);
return new PropertyError(new BindingError(exception));
}
}

14
src/Markup/Perspex.Markup/Data/Plugins/PerspexPropertyAccessorPlugin.cs

@ -33,7 +33,7 @@ namespace Perspex.Markup.Data.Plugins
/// <param name="changed">A function to call when the property changes.</param>
/// <returns>
/// An <see cref="IPropertyAccessor"/> interface through which future interactions with the
/// property will be made, or null if the property was not found.
/// property will be made.
/// </returns>
public IPropertyAccessor Start(
WeakReference reference,
@ -52,14 +52,14 @@ namespace Perspex.Markup.Data.Plugins
{
return new Accessor(new WeakReference<PerspexObject>(o), p, changed);
}
else if (instance != PerspexProperty.UnsetValue)
{
var message = $"Could not find PerspexProperty '{propertyName}' on '{instance}'";
var exception = new MissingMemberException(message);
return new PropertyError(new BindingError(exception));
}
else
{
Logger.Error(
LogArea.Binding,
this,
"Could not find PerspexProperty {Property} on {Source}",
propertyName,
instance);
return null;
}
}

39
src/Markup/Perspex.Markup/Data/Plugins/PropertyError.cs

@ -0,0 +1,39 @@
using System;
using Perspex.Data;
namespace Perspex.Markup.Data.Plugins
{
/// <summary>
/// An <see cref="IPropertyAccessor"/> that represents an error.
/// </summary>
public class PropertyError : IPropertyAccessor
{
private BindingError _error;
/// <summary>
/// Initializes a new instance of the <see cref="PropertyError"/> class.
/// </summary>
/// <param name="error">The error to report.</param>
public PropertyError(BindingError error)
{
_error = error;
}
/// <inheritdoc/>
public Type PropertyType => null;
/// <inheritdoc/>
public object Value => _error;
/// <inheritdoc/>
public void Dispose()
{
}
/// <inheritdoc/>
public bool SetValue(object value, BindingPriority priority)
{
return false;
}
}
}

2
src/Markup/Perspex.Markup/Data/PropertyAccessorNode.cs

@ -48,7 +48,7 @@ namespace Perspex.Markup.Data
{
var instance = reference.Target;
if (instance != null)
if (instance != null && instance != PerspexProperty.UnsetValue)
{
var plugin = ExpressionObserver.PropertyAccessors.FirstOrDefault(x => x.Match(reference));

2
src/Markup/Perspex.Markup/DefaultValueConverter.cs

@ -43,7 +43,7 @@ namespace Perspex.Markup
if (value != null)
{
var message = $"Could not convert {value} to {targetType}";
var message = $"Could not convert '{value}' to '{targetType}'";
return new BindingError(new InvalidCastException(message));
}

1
src/Markup/Perspex.Markup/Perspex.Markup.csproj

@ -56,6 +56,7 @@
<Compile Include="Data\Parsers\IdentifierParser.cs" />
<Compile Include="Data\Parsers\ExpressionParser.cs" />
<Compile Include="Data\Parsers\Reader.cs" />
<Compile Include="Data\Plugins\PropertyError.cs" />
<Compile Include="Data\PropertyAccessorNode.cs" />
<Compile Include="Data\ExpressionNode.cs" />
<Compile Include="Data\ExpressionObserver.cs" />

14
tests/Perspex.Markup.UnitTests/Data/ExpressionObserverTests_Property.cs

@ -7,6 +7,7 @@ using System.Reactive;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using Microsoft.Reactive.Testing;
using Perspex.Data;
using Perspex.Markup.Data;
using Perspex.UnitTests;
using Xunit;
@ -74,13 +75,17 @@ namespace Perspex.Markup.UnitTests.Data
}
[Fact]
public async void Should_Not_Have_Value_For_Broken_Chain()
public async void Should_Return_BindingError_For_Broken_Chain()
{
var data = new { Foo = new { Bar = 1 } };
var target = new ExpressionObserver(data, "Foo.Bar.Baz");
var result = await target.Take(1);
Assert.Equal(PerspexProperty.UnsetValue, result);
Assert.IsType<BindingError>(result);
var error = result as BindingError;
Assert.IsType<MissingMemberException>(error.Exception);
Assert.Equal("Could not find CLR property 'Baz' on '1'", error.Exception.Message);
}
[Fact]
@ -209,7 +214,10 @@ namespace Perspex.Markup.UnitTests.Data
data.Next = breaking;
data.Next = new Class2 { Bar = "baz" };
Assert.Equal(new[] { "bar", PerspexProperty.UnsetValue, "baz" }, result);
Assert.Equal(3, result.Count);
Assert.Equal("bar", result[0]);
Assert.IsType<BindingError>(result[1]);
Assert.Equal("baz", result[2]);
sub.Dispose();

Loading…
Cancel
Save