Click here to Skip to main content
15,888,733 members
Articles / Desktop Programming / XAML

YouGrade - Silverlight Multimedia Exam Suite

Rate me:
Please Sign up or sign in to vote.
4.96/5 (62 votes)
5 Jun 2010CPOL16 min read 133.5K   3.1K   133  
A multimedia exam suite built on Silverlight and Youtube
//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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Instructor / Trainer Alura Cursos Online
Brazil Brazil

Comments and Discussions