Browse Source

Handle null and UnsetValue in ExpressionSubject.

pull/278/head
Steven Kirk 11 years ago
parent
commit
16825ac45e
  1. 4
      samples/XamlTestApplicationPcl/Views/MainWindow.paml
  2. 22
      src/Markup/Perspex.Markup/Binding/ExpressionSubject.cs
  3. 2
      src/Perspex.Base/PriorityValue.cs
  4. 25
      tests/Perspex.Base.UnitTests/PerspexObjectTests_Direct.cs
  5. 12
      tests/Perspex.Base.UnitTests/PerspexObjectTests_Validation.cs
  6. 135
      tests/Perspex.Markup.UnitTests/Binding/ExpressionSubjectTests.cs
  7. 1
      tests/Perspex.Markup.UnitTests/Perspex.Markup.UnitTests.csproj

4
samples/XamlTestApplicationPcl/Views/MainWindow.paml

@ -5,9 +5,9 @@
Title="Perspex Test Application" Height="350" Width="525" SizeToContent="WidthAndHeight" >
<Grid RowDefinitions="Auto,*,Auto" ColumnDefinitions="*,*">
<TabControl Grid.Row="1" Grid.ColumnSpan="2" Padding="5">
<TabControl.Transition>
<!--<TabControl.Transition>
<PageSlide Duration="0.25" />
</TabControl.Transition>
</TabControl.Transition>-->
<TabItem Header="Buttons">
<StackPanel HorizontalAlignment="Center" Width="200" VerticalAlignment="Center">
<StackPanel.Styles>

22
src/Markup/Perspex.Markup/Binding/ExpressionSubject.cs

@ -5,6 +5,7 @@ using System;
using System.Globalization;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using Perspex.Utilities;
namespace Perspex.Markup.Binding
{
@ -82,7 +83,14 @@ namespace Perspex.Markup.Binding
{
try
{
return _converter.Convert(value, type, null, CultureInfo.CurrentUICulture);
if (value == null || value == PerspexProperty.UnsetValue)
{
return TypeUtilities.Default(type);
}
else
{
return _converter.Convert(value, type, null, CultureInfo.CurrentUICulture);
}
}
catch
{
@ -95,8 +103,16 @@ namespace Perspex.Markup.Binding
{
try
{
result = _converter.ConvertBack(value, type, null, CultureInfo.CurrentUICulture);
return true;
if (value == null || value == PerspexProperty.UnsetValue)
{
result = TypeUtilities.Default(type);
return true;
}
else
{
result = _converter.ConvertBack(value, type, null, CultureInfo.CurrentUICulture);
return true;
}
}
catch
{

2
src/Perspex.Base/PriorityValue.cs

@ -216,7 +216,7 @@ namespace Perspex
{
var old = _value;
if (_validate != null)
if (_validate != null && value != PerspexProperty.UnsetValue)
{
value = _validate(value);
}

25
tests/Perspex.Base.UnitTests/PerspexObjectTests_Direct.cs

@ -54,6 +54,16 @@ namespace Perspex.Base.UnitTests
Assert.Equal("newvalue", target.Foo);
}
[Fact]
public void SetValue_NonGeneric_Coerces_UnsetValue_To_Default_Value()
{
var target = new Class1();
target.SetValue((PerspexProperty)Class1.BazProperty, PerspexProperty.UnsetValue);
Assert.Equal(0, target.Baz);
}
[Fact]
public void SetValue_Raises_PropertyChanged()
{
@ -148,6 +158,21 @@ namespace Perspex.Base.UnitTests
Assert.Equal("second", target.Foo);
}
[Fact]
public void Bind_NonGeneric_Coerces_UnsetValue()
{
var target = new Class1();
var source = new Subject<object>();
var sub = target.Bind((PerspexProperty)Class1.BazProperty, source);
Assert.Equal(5, target.Baz);
source.OnNext(6);
Assert.Equal(6, target.Baz);
source.OnNext(PerspexProperty.UnsetValue);
Assert.Equal(0, target.Baz);
}
[Fact]
public void Bind_Handles_Wrong_Type()
{

12
tests/Perspex.Base.UnitTests/PerspexObjectTests_Validation.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.Reactive.Subjects;
using Xunit;
namespace Perspex.Base.UnitTests
@ -57,6 +58,17 @@ namespace Perspex.Base.UnitTests
Assert.Equal(50, target.GetValue(Class1.QuxProperty));
}
[Fact]
public void Binding_To_UnsetValue_Doesnt_Throw()
{
var target = new Class1();
var source = new Subject<object>();
target.Bind(Class1.QuxProperty, source);
source.OnNext(PerspexProperty.UnsetValue);
}
private class Class1 : PerspexObject
{
public static readonly PerspexProperty<int> QuxProperty =

135
tests/Perspex.Markup.UnitTests/Binding/ExpressionSubjectTests.cs

@ -0,0 +1,135 @@
// 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.Reactive.Linq;
using Perspex.Markup.Binding;
using Xunit;
namespace Perspex.Markup.UnitTests.Binding
{
public class ExpressionSubjectTests
{
[Fact]
public async void Should_Get_Simple_Property_Value()
{
var data = new Class1 { StringValue = "foo" };
var target = new ExpressionSubject(new ExpressionObserver(data, "StringValue"), typeof(string));
var result = await target.Take(1);
Assert.Equal("foo", result);
}
[Fact]
public void Should_Set_Simple_Property_Value()
{
var data = new Class1 { StringValue = "foo" };
var target = new ExpressionSubject(new ExpressionObserver(data, "StringValue"), typeof(string));
target.OnNext("bar");
Assert.Equal("bar", data.StringValue);
}
[Fact]
public async void Should_Convert_Get_String_To_Double()
{
var data = new Class1 { StringValue = "5.6" };
var target = new ExpressionSubject(new ExpressionObserver(data, "StringValue"), typeof(double));
var result = await target.Take(1);
Assert.Equal(5.6, result);
}
[Fact]
public async void Should_Convert_Get_Invalid_Double_String_To_UnsetValue()
{
var data = new Class1 { StringValue = "foo" };
var target = new ExpressionSubject(new ExpressionObserver(data, "StringValue"), typeof(double));
var result = await target.Take(1);
Assert.Equal(PerspexProperty.UnsetValue, result);
}
[Fact]
public async void Should_Coerce_Get_Null_String_To_Double_Deafult_Value()
{
var data = new Class1 { StringValue = null };
var target = new ExpressionSubject(new ExpressionObserver(data, "StringValue"), typeof(double));
var result = await target.Take(1);
Assert.Equal(0.0, result);
}
[Fact]
public void Should_Convert_Set_String_To_Double()
{
var data = new Class1 { StringValue = "5.6" };
var target = new ExpressionSubject(new ExpressionObserver(data, "StringValue"), typeof(double));
target.OnNext(6.7);
Assert.Equal("6.7", data.StringValue);
}
[Fact]
public async void Should_Convert_Get_Double_To_String()
{
var data = new Class1 { DoubleValue = 5.6 };
var target = new ExpressionSubject(new ExpressionObserver(data, "DoubleValue"), typeof(string));
var result = await target.Take(1);
Assert.Equal("5.6", result);
}
[Fact]
public void Should_Convert_Set_Double_To_String()
{
var data = new Class1 { DoubleValue = 5.6 };
var target = new ExpressionSubject(new ExpressionObserver(data, "DoubleValue"), typeof(string));
target.OnNext("6.7");
Assert.Equal(6.7, data.DoubleValue);
}
[Fact]
public void Should_Ignore_Set_Invalid_Double_String()
{
var data = new Class1 { DoubleValue = 5.6 };
var target = new ExpressionSubject(new ExpressionObserver(data, "DoubleValue"), typeof(string));
target.OnNext("foo");
Assert.Equal(5.6, data.DoubleValue);
}
[Fact]
public void Should_Coerce_Set_Null_To_Default_Value()
{
var data = new Class1 { DoubleValue = 5.6 };
var target = new ExpressionSubject(new ExpressionObserver(data, "DoubleValue"), typeof(string));
target.OnNext(null);
Assert.Equal(0, data.DoubleValue);
}
[Fact]
public void Should_Coerce_Set_UnsetValue_To_Default_Value()
{
var data = new Class1 { DoubleValue = 5.6 };
var target = new ExpressionSubject(new ExpressionObserver(data, "DoubleValue"), typeof(string));
target.OnNext(PerspexProperty.UnsetValue);
Assert.Equal(0, data.DoubleValue);
}
private class Class1
{
public string StringValue { get; set; }
public double DoubleValue { get; set; }
}
}
}

1
tests/Perspex.Markup.UnitTests/Perspex.Markup.UnitTests.csproj

@ -73,6 +73,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Binding\ExpressionNodeBuilderTests_Errors.cs" />
<Compile Include="Binding\ExpressionSubjectTests.cs" />
<Compile Include="Binding\ExpressionObserverTests_Observable.cs" />
<Compile Include="Binding\ExpressionObserverTests_SetValue.cs" />
<Compile Include="Binding\ExpressionObserverTests_Task.cs" />

Loading…
Cancel
Save