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>
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>
/// Gets or sets the binding mode.
/// </summary>
@ -104,7 +109,8 @@ namespace Perspex.Markup.Xaml.Data
observer,
targetProperty?.PropertyType ?? typeof(object),
Converter ?? DefaultValueConverter.Instance,
ConverterParameter);
ConverterParameter,
FallbackValue);
}
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 object ConverterParameter { get; set; }
public string ElementName { get; set; }
public object FallbackValue { get; set; }
public BindingMode Mode { get; set; }
public string Path { get; set; }
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 string ElementName { get; set; }
public object FallbackValue { get; set; }
public BindingMode Mode { get; set; }
public string Path { get; set; }
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 Type _targetType;
private readonly object _fallbackValue;
/// <summary>
/// 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="targetType">The type to convert the value to.</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(
ExpressionObserver inner,
Type targetType,
IValueConverter converter,
object converterParameter = null)
object converterParameter = null,
object fallbackValue = null)
{
Contract.Requires<ArgumentNullException>(inner != null);
Contract.Requires<ArgumentNullException>(targetType != null);
@ -49,6 +56,7 @@ namespace Perspex.Markup.Data
_targetType = targetType;
Converter = converter;
ConverterParameter = converterParameter;
_fallbackValue = fallbackValue;
}
/// <summary>
@ -99,13 +107,23 @@ namespace Perspex.Markup.Data
/// <inheritdoc/>
public IDisposable Subscribe(IObserver<object> observer)
{
return _inner
.Select(x => Converter.Convert(
x,
_targetType,
ConverterParameter,
CultureInfo.CurrentUICulture))
.Subscribe(observer);
return _inner.Select(ConvertValue).Subscribe(observer);
}
private object ConvertValue(object value)
{
var converted = Converter.Convert(
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);
}
[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>
/// Tests a problem discovered with ListBox with selection.
/// </summary>

Loading…
Cancel
Save