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) private object ConvertValue(object value)
{ {
var converted = Converter.Convert( var converted =
value as BindingError ??
Converter.Convert(
value, value,
_targetType, _targetType,
ConverterParameter, 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> /// <param name="changed">A function to call when the property changes.</param>
/// <returns> /// <returns>
/// An <see cref="IPropertyAccessor"/> interface through which future interactions with the /// 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> /// </returns>
IPropertyAccessor Start( IPropertyAccessor Start(
WeakReference reference, 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> /// <param name="changed">A function to call when the property changes.</param>
/// <returns> /// <returns>
/// An <see cref="IPropertyAccessor"/> interface through which future interactions with the /// 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> /// </returns>
public IPropertyAccessor Start( public IPropertyAccessor Start(
WeakReference reference, WeakReference reference,
@ -58,14 +58,9 @@ namespace Perspex.Markup.Data.Plugins
} }
else else
{ {
Logger.Error( var message = $"Could not find CLR property '{propertyName}' on '{instance}'";
LogArea.Binding, var exception = new MissingMemberException(message);
this, return new PropertyError(new BindingError(exception));
"Could not find CLR property {Property} on {Source}",
propertyName,
instance);
return null;
} }
} }

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> /// <param name="changed">A function to call when the property changes.</param>
/// <returns> /// <returns>
/// An <see cref="IPropertyAccessor"/> interface through which future interactions with the /// 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> /// </returns>
public IPropertyAccessor Start( public IPropertyAccessor Start(
WeakReference reference, WeakReference reference,
@ -52,14 +52,14 @@ namespace Perspex.Markup.Data.Plugins
{ {
return new Accessor(new WeakReference<PerspexObject>(o), p, changed); 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 else
{ {
Logger.Error(
LogArea.Binding,
this,
"Could not find PerspexProperty {Property} on {Source}",
propertyName,
instance);
return null; 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; var instance = reference.Target;
if (instance != null) if (instance != null && instance != PerspexProperty.UnsetValue)
{ {
var plugin = ExpressionObserver.PropertyAccessors.FirstOrDefault(x => x.Match(reference)); 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) 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)); 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\IdentifierParser.cs" />
<Compile Include="Data\Parsers\ExpressionParser.cs" /> <Compile Include="Data\Parsers\ExpressionParser.cs" />
<Compile Include="Data\Parsers\Reader.cs" /> <Compile Include="Data\Parsers\Reader.cs" />
<Compile Include="Data\Plugins\PropertyError.cs" />
<Compile Include="Data\PropertyAccessorNode.cs" /> <Compile Include="Data\PropertyAccessorNode.cs" />
<Compile Include="Data\ExpressionNode.cs" /> <Compile Include="Data\ExpressionNode.cs" />
<Compile Include="Data\ExpressionObserver.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.Linq;
using System.Reactive.Subjects; using System.Reactive.Subjects;
using Microsoft.Reactive.Testing; using Microsoft.Reactive.Testing;
using Perspex.Data;
using Perspex.Markup.Data; using Perspex.Markup.Data;
using Perspex.UnitTests; using Perspex.UnitTests;
using Xunit; using Xunit;
@ -74,13 +75,17 @@ namespace Perspex.Markup.UnitTests.Data
} }
[Fact] [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 data = new { Foo = new { Bar = 1 } };
var target = new ExpressionObserver(data, "Foo.Bar.Baz"); var target = new ExpressionObserver(data, "Foo.Bar.Baz");
var result = await target.Take(1); 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] [Fact]
@ -209,7 +214,10 @@ namespace Perspex.Markup.UnitTests.Data
data.Next = breaking; data.Next = breaking;
data.Next = new Class2 { Bar = "baz" }; 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(); sub.Dispose();

Loading…
Cancel
Save