Browse Source

Implemented Binding.FallbackValue.

Closes #238.
pull/404/head
Steven Kirk 10 years ago
parent
commit
ffbd694bf7
  1. 8
      src/Markup/Perspex.Markup.Xaml/Data/Binding.cs
  2. 1
      src/Markup/Perspex.Markup.Xaml/MarkupExtensions/BindingExtension.cs
  3. 1
      src/Markup/Perspex.Markup.Xaml/MarkupExtensions/TemplateBindingExtension.cs
  4. 36
      src/Markup/Perspex.Markup/Data/ExpressionSubject.cs
  5. 34
      tests/Perspex.Markup.Xaml.UnitTests/Data/BindingTests.cs

8
src/Markup/Perspex.Markup.Xaml/Data/Binding.cs

@ -31,6 +31,11 @@ namespace Perspex.Markup.Xaml.Data
/// </summary> /// </summary>
public string ElementName { get; set; } public string ElementName { get; set; }
/// <summary>
/// Gets or sets the value to use when the binding is unable to produce a value.
/// </summary>
public object FallbackValue { get; set; }
/// <summary> /// <summary>
/// Gets or sets the binding mode. /// Gets or sets the binding mode.
/// </summary> /// </summary>
@ -104,7 +109,8 @@ namespace Perspex.Markup.Xaml.Data
observer, observer,
targetProperty?.PropertyType ?? typeof(object), targetProperty?.PropertyType ?? typeof(object),
Converter ?? DefaultValueConverter.Instance, Converter ?? DefaultValueConverter.Instance,
ConverterParameter); ConverterParameter,
FallbackValue);
} }
private static PathInfo ParsePath(string path) private static PathInfo ParsePath(string path)

1
src/Markup/Perspex.Markup.Xaml/MarkupExtensions/BindingExtension.cs

@ -34,6 +34,7 @@ namespace Perspex.Markup.Xaml.MarkupExtensions
public IValueConverter Converter { get; set; } public IValueConverter Converter { get; set; }
public object ConverterParameter { get; set; } public object ConverterParameter { get; set; }
public string ElementName { get; set; } public string ElementName { get; set; }
public object FallbackValue { get; set; }
public BindingMode Mode { get; set; } public BindingMode Mode { get; set; }
public string Path { get; set; } public string Path { get; set; }
public BindingPriority Priority { get; set; } = BindingPriority.LocalValue; public BindingPriority Priority { get; set; } = BindingPriority.LocalValue;

1
src/Markup/Perspex.Markup.Xaml/MarkupExtensions/TemplateBindingExtension.cs

@ -33,6 +33,7 @@ namespace Perspex.Markup.Xaml.MarkupExtensions
public IValueConverter Converter { get; set; } public IValueConverter Converter { get; set; }
public string ElementName { get; set; } public string ElementName { get; set; }
public object FallbackValue { get; set; }
public BindingMode Mode { get; set; } public BindingMode Mode { get; set; }
public string Path { get; set; } public string Path { get; set; }
public BindingPriority Priority { get; set; } = BindingPriority.TemplatedParent; public BindingPriority Priority { get; set; } = BindingPriority.TemplatedParent;

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

@ -17,6 +17,7 @@ namespace Perspex.Markup.Data
{ {
private readonly ExpressionObserver _inner; private readonly ExpressionObserver _inner;
private readonly Type _targetType; private readonly Type _targetType;
private readonly object _fallbackValue;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ExpressionObserver"/> class. /// Initializes a new instance of the <see cref="ExpressionObserver"/> class.
@ -34,12 +35,18 @@ namespace Perspex.Markup.Data
/// <param name="inner">The <see cref="ExpressionObserver"/>.</param> /// <param name="inner">The <see cref="ExpressionObserver"/>.</param>
/// <param name="targetType">The type to convert the value to.</param> /// <param name="targetType">The type to convert the value to.</param>
/// <param name="converter">The value converter to use.</param> /// <param name="converter">The value converter to use.</param>
/// <param name="converterParameter">A parameter to pass to <paramref name="converter"/>.</param> /// <param name="converterParameter">
/// A parameter to pass to <paramref name="converter"/>.
/// </param>
/// <param name="fallbackValue">
/// The value to use when the binding is unable to produce a value.
/// </param>
public ExpressionSubject( public ExpressionSubject(
ExpressionObserver inner, ExpressionObserver inner,
Type targetType, Type targetType,
IValueConverter converter, IValueConverter converter,
object converterParameter = null) object converterParameter = null,
object fallbackValue = null)
{ {
Contract.Requires<ArgumentNullException>(inner != null); Contract.Requires<ArgumentNullException>(inner != null);
Contract.Requires<ArgumentNullException>(targetType != null); Contract.Requires<ArgumentNullException>(targetType != null);
@ -49,6 +56,7 @@ namespace Perspex.Markup.Data
_targetType = targetType; _targetType = targetType;
Converter = converter; Converter = converter;
ConverterParameter = converterParameter; ConverterParameter = converterParameter;
_fallbackValue = fallbackValue;
} }
/// <summary> /// <summary>
@ -99,13 +107,23 @@ namespace Perspex.Markup.Data
/// <inheritdoc/> /// <inheritdoc/>
public IDisposable Subscribe(IObserver<object> observer) public IDisposable Subscribe(IObserver<object> observer)
{ {
return _inner return _inner.Select(ConvertValue).Subscribe(observer);
.Select(x => Converter.Convert( }
x,
_targetType, private object ConvertValue(object value)
ConverterParameter, {
CultureInfo.CurrentUICulture)) var converted = Converter.Convert(
.Subscribe(observer); value,
_targetType,
ConverterParameter,
CultureInfo.CurrentUICulture);
if (converted == PerspexProperty.UnsetValue && _fallbackValue != null)
{
converted = _fallbackValue;
}
return converted;
} }
} }
} }

34
tests/Perspex.Markup.Xaml.UnitTests/Data/BindingTests.cs

@ -206,6 +206,40 @@ namespace Perspex.Markup.Xaml.UnitTests.Data
Assert.Same("foo", ((ExpressionSubject)result).ConverterParameter); Assert.Same("foo", ((ExpressionSubject)result).ConverterParameter);
} }
[Fact]
public void Should_Return_FallbackValue_When_Path_Not_Resolved()
{
var target = new TextBlock();
var source = new Source();
var binding = new Binding
{
Source = source,
Path = "BadPath",
FallbackValue = "foofallback",
};
target.Bind(TextBlock.TextProperty, binding);
Assert.Equal("foofallback", target.Text);
}
[Fact]
public void Should_Return_FallbackValue_When_Invalid_Source_Type()
{
var target = new ProgressBar();
var source = new Source { Foo = "foo" };
var binding = new Binding
{
Source = source,
Path = "Foo",
FallbackValue = 42,
};
target.Bind(ProgressBar.ValueProperty, binding);
Assert.Equal(42, target.Value);
}
/// <summary> /// <summary>
/// Tests a problem discovered with ListBox with selection. /// Tests a problem discovered with ListBox with selection.
/// </summary> /// </summary>

Loading…
Cancel
Save