12 changed files with 211 additions and 10 deletions
@ -0,0 +1,7 @@ |
|||||
|
namespace Perspex.Markup.Xaml.Data |
||||
|
{ |
||||
|
public interface IBinding |
||||
|
{ |
||||
|
void Bind(IObservablePropertyBag instance, PerspexProperty property); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,90 @@ |
|||||
|
// 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; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Globalization; |
||||
|
using System.Linq; |
||||
|
using System.Reactive.Linq; |
||||
|
using System.Reactive.Subjects; |
||||
|
using OmniXaml.TypeConversion; |
||||
|
using Perspex.Controls; |
||||
|
using Perspex.Markup.Data; |
||||
|
using Perspex.Metadata; |
||||
|
|
||||
|
namespace Perspex.Markup.Xaml.Data |
||||
|
{ |
||||
|
public class MultiBinding : IBinding |
||||
|
{ |
||||
|
private readonly ITypeConverterProvider _typeConverterProvider; |
||||
|
|
||||
|
public MultiBinding() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public MultiBinding(ITypeConverterProvider typeConverterProvider) |
||||
|
{ |
||||
|
_typeConverterProvider = typeConverterProvider; |
||||
|
} |
||||
|
|
||||
|
[Content] |
||||
|
public IList<Binding> Bindings { get; } = new List<Binding>(); |
||||
|
public IMultiValueConverter Converter { get; set; } |
||||
|
public BindingMode Mode { get; set; } |
||||
|
public BindingPriority Priority { get; set; } |
||||
|
public RelativeSource RelativeSource { get; set; } |
||||
|
public string SourcePropertyPath { get; set; } |
||||
|
|
||||
|
public void Bind(IObservablePropertyBag instance, PerspexProperty property) |
||||
|
{ |
||||
|
var subject = CreateSubject(instance, property); |
||||
|
|
||||
|
if (subject != null) |
||||
|
{ |
||||
|
Bind(instance, property, subject); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public ISubject<object> CreateSubject( |
||||
|
IObservablePropertyBag instance, |
||||
|
PerspexProperty property) |
||||
|
{ |
||||
|
if (Converter == null) |
||||
|
{ |
||||
|
throw new NotSupportedException("MultiBinding without Converter not currently supported."); |
||||
|
} |
||||
|
|
||||
|
var result = new Subject<object>(); |
||||
|
var children = Bindings.Select(x => x.CreateExpressionSubject(instance, property)); |
||||
|
var input = Observable.CombineLatest(children).Select(x => |
||||
|
Converter.Convert(x, property.PropertyType, null, CultureInfo.CurrentUICulture)); |
||||
|
input.Subscribe(result); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
internal void Bind(IObservablePropertyBag target, PerspexProperty property, ISubject<object> subject) |
||||
|
{ |
||||
|
var mode = Mode == BindingMode.Default ? |
||||
|
property.DefaultBindingMode : Mode; |
||||
|
|
||||
|
switch (mode) |
||||
|
{ |
||||
|
case BindingMode.Default: |
||||
|
case BindingMode.OneWay: |
||||
|
target.Bind(property, subject, Priority); |
||||
|
break; |
||||
|
case BindingMode.TwoWay: |
||||
|
throw new NotSupportedException("TwoWay MultiBinding not currently supported."); |
||||
|
case BindingMode.OneTime: |
||||
|
target.GetObservable(Control.DataContextProperty).Subscribe(dataContext => |
||||
|
{ |
||||
|
subject.Take(1).Subscribe(x => target.SetValue(property, x, Priority)); |
||||
|
}); |
||||
|
break; |
||||
|
case BindingMode.OneWayToSource: |
||||
|
target.GetObservable(property).Subscribe(subject); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
// 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.Linq; |
||||
|
|
||||
|
namespace Perspex.Markup |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Provides a set of useful <see cref="IValueConverter"/>s for working with string values.
|
||||
|
/// </summary>
|
||||
|
public static class BoolConverters |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// A multi-value converter that returns true if all inputs are true.
|
||||
|
/// </summary>
|
||||
|
public static readonly IMultiValueConverter And = |
||||
|
new FuncMultiValueConverter<bool, bool>(x => x.All(y => y)); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
// 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; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Globalization; |
||||
|
using System.Linq; |
||||
|
|
||||
|
namespace Perspex.Markup |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// A general purpose <see cref="IValueConverter"/> that uses a <see cref="Func{T1, TResult}"/>
|
||||
|
/// to provide the converter logic.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TIn">The type of the inputs.</typeparam>
|
||||
|
/// <typeparam name="TOut">The output type.</typeparam>
|
||||
|
public class FuncMultiValueConverter<TIn, TOut> : IMultiValueConverter |
||||
|
{ |
||||
|
private Func<IEnumerable<TIn>, TOut> _convert; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="FuncValueConverter{TIn, TOut}"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="convert">The convert function.</param>
|
||||
|
public FuncMultiValueConverter(Func<IEnumerable<TIn>, TOut> convert) |
||||
|
{ |
||||
|
_convert = convert; |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public object Convert(IList<object> values, Type targetType, object parameter, CultureInfo culture) |
||||
|
{ |
||||
|
return _convert(values.OfType<TIn>()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
// 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; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Globalization; |
||||
|
|
||||
|
namespace Perspex.Markup |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Converts multi-binding inputs to a final value.
|
||||
|
/// </summary>
|
||||
|
public interface IMultiValueConverter |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Converts multi-binding inputs to a final value.
|
||||
|
/// </summary>
|
||||
|
/// <param name="values">The values to convert.</param>
|
||||
|
/// <param name="targetType">The type of the target.</param>
|
||||
|
/// <param name="parameter">A user-defined parameter.</param>
|
||||
|
/// <param name="culture">The culture to use.</param>
|
||||
|
/// <returns>The converted value.</returns>
|
||||
|
/// <remarks>
|
||||
|
/// This method should not throw exceptions. If the value is not convertible, return
|
||||
|
/// <see cref="PerspexProperty.UnsetValue"/>. Any exception thrown will be treated as
|
||||
|
/// an application exception.
|
||||
|
/// </remarks>
|
||||
|
object Convert(IList<object> values, Type targetType, object parameter, CultureInfo culture); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue