using System; using System.Reflection; using Windows.UI.Xaml; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Markup; using Microsoft.Xaml.Interactivity; namespace LiveCharts.Uwp.Components.MultiBinding { /// /// The behavior that enables multiple binding. /// [ContentProperty(Name = "Items")] [TypeConstraint(typeof(FrameworkElement))] public class MultiBindingBehavior : Behavior { /// /// Gets the collection within this instance. /// /// One or more objects. public MultiBindingItemCollection Items { get { return (MultiBindingItemCollection)GetValue(ItemsProperty); } private set { SetValue(ItemsProperty, value); } } /// /// Identifier for the dependency property. /// public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(nameof(Items), typeof(MultiBindingItemCollection), typeof(MultiBindingBehavior), null); /// /// Gets or sets the path to the binding source property. /// /// The path to the binding source property. public string PropertyName { get { return (string)GetValue(PropertyNameProperty); } set { SetValue(PropertyNameProperty, value); } } /// /// Identifier for the dependency property. /// public static readonly DependencyProperty PropertyNameProperty = DependencyProperty.Register(nameof(PropertyName), typeof(string), typeof(MultiBindingBehavior), new PropertyMetadata(null, OnPropertyChanged)); /// /// Gets or sets the converter to use to convert the source values to or from the target value. /// /// A resource reference to a class that implements the interface, which includes implementations of the and methods. public IValueConverter Converter { get { return (IValueConverter)GetValue(ConverterProperty); } set { SetValue(ConverterProperty, value); } } /// /// Identifier for the dependency property. /// public static readonly DependencyProperty ConverterProperty = DependencyProperty.Register(nameof(Converter), typeof(IValueConverter), typeof(MultiBindingBehavior), new PropertyMetadata(null, OnPropertyChanged)); /// /// Gets or sets an optional parameter to pass to the converter as additional information. /// /// A value of the type expected by the converter, which might be an object element or a string depending on the definition and XAML capabilities both of the property type being used and of the implementation of the converter. public object ConverterParameter { get { return GetValue(ConverterParameterProperty); } set { SetValue(ConverterParameterProperty, value); } } /// /// Identifier for the dependency property. /// public static readonly DependencyProperty ConverterParameterProperty = DependencyProperty.Register(nameof(ConverterParameter), typeof(object), typeof(MultiBindingBehavior), new PropertyMetadata(null, OnPropertyChanged)); /// /// Gets or sets a value that indicates the direction of the data flow in the binding. /// /// A value that indicates the direction of the data flow in the binding. public BindingMode Mode { get { return (BindingMode)GetValue(ModeProperty); } set { SetValue(ModeProperty, value); } } /// /// Identifier for the dependency property. /// public static readonly DependencyProperty ModeProperty = DependencyProperty.Register(nameof(Mode), typeof(BindingMode), typeof(MultiBindingBehavior), new PropertyMetadata(BindingMode.OneWay, OnPropertyChanged)); private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var multiBindingBehavior = (MultiBindingBehavior)d; multiBindingBehavior.Update(); } /// /// Initializes a new instance of the class. /// public MultiBindingBehavior() { Items = new MultiBindingItemCollection(); } /// /// Called after the behavior is attached to an AssociatedObject. /// /// Override this to hook up functionality to the AssociatedObject. protected override void OnAttached() { base.OnAttached(); Update(); } private void Update() { if (AssociatedObject == null || string.IsNullOrEmpty(PropertyName)) { return; } var targetProperty = PropertyName; Type targetType; if (targetProperty.Contains(".")) { var propertyNameParts = targetProperty.Split('.'); targetType = Type.GetType(string.Format("Windows.UI.Xaml.Controls.{0}, Windows", propertyNameParts[0])); targetProperty = propertyNameParts[1]; } else { targetType = AssociatedObject.GetType(); } PropertyInfo targetDependencyPropertyField = null; while (targetDependencyPropertyField == null && targetType != null) { var targetTypeInfo = targetType.GetTypeInfo(); targetDependencyPropertyField = targetTypeInfo.GetDeclaredProperty(targetProperty + "Property"); targetType = targetTypeInfo.BaseType; } if (targetDependencyPropertyField == null) return; var targetDependencyProperty = (DependencyProperty)targetDependencyPropertyField.GetValue(null); var binding = new Binding() { Path = new PropertyPath("Value"), Source = Items, Converter = Converter, ConverterParameter = ConverterParameter, Mode = Mode }; BindingOperations.SetBinding(AssociatedObject, targetDependencyProperty, binding); } } }