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