|
//This is the Binding Helper class that emulates the element binding in Silverlight
//Please refer to Colin Eberhardt's article:
//http://www.scottlogic.co.uk/blog/colin/2009/02/elementname-binding-in-silverlight-via-attached-behaviours/
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Windows.Data;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
namespace SilverlightBinding
{
public class BindingProperties
{
public string SourceProperty { get; set; }
public string ElementName { get; set; }
public string TargetProperty { get; set; }
public IValueConverter Converter { get; set; }
public object ConverterParameter { get; set; }
}
public static class BindingHelper
{
public class ValueObject : INotifyPropertyChanged
{
private object _value;
public object Value
{
get { return _value; }
set
{
_value = value;
OnPropertyChanged("Value");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public static BindingProperties GetBinding(DependencyObject obj)
{
return (BindingProperties)obj.GetValue(BindingProperty);
}
public static void SetBinding(DependencyObject obj, BindingProperties value)
{
obj.SetValue(BindingProperty, value);
}
public static readonly DependencyProperty BindingProperty =
DependencyProperty.RegisterAttached("Binding", typeof(BindingProperties), typeof(BindingHelper),
new PropertyMetadata(null, OnBinding));
/// <summary>
/// property change event handler for SelectAllButtonTemplate
/// </summary>
private static void OnBinding(
DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
FrameworkElement targetElement = depObj as FrameworkElement;
targetElement.Loaded += new RoutedEventHandler(TargetElement_Loaded);
}
private static void TargetElement_Loaded(object sender, RoutedEventArgs e)
{
FrameworkElement targetElement = sender as FrameworkElement;
// get the value of our attached property
BindingProperties bindingProperties = GetBinding(targetElement);
// perform our 'ElementName' lookup
FrameworkElement sourceElement = targetElement.FindName(bindingProperties.ElementName) as FrameworkElement;
// bind them
CreateRelayBinding(targetElement, sourceElement, bindingProperties);
}
private static readonly BindingFlags dpFlags = BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy;
private struct RelayBindingKey
{
public DependencyProperty dependencyObject;
public FrameworkElement frameworkElement;
}
private static Dictionary<RelayBindingKey, ValueObject> relayBindings = new Dictionary<RelayBindingKey, ValueObject>();
private static void CreateRelayBinding(FrameworkElement targetElement, FrameworkElement sourceElement,
BindingProperties bindingProperties)
{
string sourcePropertyName = bindingProperties.SourceProperty + "Property";
string targetPropertyName = bindingProperties.TargetProperty + "Property";
// find the source dependency property
FieldInfo[] sourceFields = sourceElement.GetType().GetFields(dpFlags);
FieldInfo sourceDependencyPropertyField = sourceFields.First(i => i.Name == sourcePropertyName);
DependencyProperty sourceDependencyProperty = sourceDependencyPropertyField.GetValue(null) as DependencyProperty;
// find the target dependency property
FieldInfo[] targetFields = targetElement.GetType().GetFields(dpFlags);
FieldInfo targetDependencyPropertyField = targetFields.First(i => i.Name == targetPropertyName);
DependencyProperty targetDependencyProperty = targetDependencyPropertyField.GetValue(null) as DependencyProperty;
ValueObject relayObject;
bool relayObjectBoundToSource = false;
// create a key that identifies this source binding
RelayBindingKey key = new RelayBindingKey()
{
dependencyObject = sourceDependencyProperty,
frameworkElement = sourceElement
};
// do we already have a binding to this property?
if (relayBindings.ContainsKey(key))
{
relayObject = relayBindings[key];
relayObjectBoundToSource = true;
}
else
{
// create a relay binding between the two elements
relayObject = new ValueObject();
}
// initialise the relay object with the source dependency property value
relayObject.Value = sourceElement.GetValue(sourceDependencyProperty);
// create the binding for our target element to the relay object, this binding will
// include the value converter
Binding targetToRelay = new Binding();
targetToRelay.Source = relayObject;
targetToRelay.Path = new PropertyPath("Value");
targetToRelay.Mode = BindingMode.TwoWay;
targetToRelay.Converter = bindingProperties.Converter;
targetToRelay.ConverterParameter = bindingProperties.ConverterParameter;
// set the binding on our target element
targetElement.SetBinding(targetDependencyProperty, targetToRelay);
if (!relayObjectBoundToSource)
{
// create the binding for our source element to the relay object
Binding sourceToRelay = new Binding();
sourceToRelay.Source = relayObject;
sourceToRelay.Path = new PropertyPath("Value");
sourceToRelay.Mode = BindingMode.TwoWay;
// set the binding on our source element
sourceElement.SetBinding(sourceDependencyProperty, sourceToRelay);
relayBindings.Add(key, relayObject);
}
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.