Click here to Skip to main content
15,881,455 members
Articles / Desktop Programming / WPF

Catel - Part 4 of n: Unit testing with Catel

Rate me:
Please Sign up or sign in to vote.
4.55/5 (10 votes)
28 Jan 2011CPOL11 min read 48.8K   572   11  
This article explains how to write unit tests for MVVM using Catel.
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Windows;
using System.Windows.Markup;

namespace Catel.Windows.Data
{

    /// <summary>
    /// Class that represents a bound property value for a non-bindable property.
    /// </summary>
    /// <remarks>
    /// This code originally comes from: http://www.wpfmentor.com/2009/01/how-to-add-binding-to-commandparameter.html.
    /// </remarks>
    public class DataResource : Freezable
    {
        #region Variables
        #endregion

        #region Constructor & destructor
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the binding target.
        /// </summary>
        /// <value>The binding target.</value>
        public object BindingTarget
        {
            get { return (object)GetValue(BindingTargetProperty); }
            set { SetValue(BindingTargetProperty, value); }
        }

        /// <summary>
        /// Identifies the <see cref="BindingTarget"/> dependency property.
        /// </summary>
        /// <value>
        /// The identifier for the <see cref="BindingTarget"/> dependency property.
        /// </value>
        public static readonly DependencyProperty BindingTargetProperty = DependencyProperty.Register("BindingTarget", typeof(object), typeof(DataResource), new UIPropertyMetadata(null));
        #endregion

        #region Methods
        /// <summary>
        /// Creates an instance of the specified type using that type's default constructor. 
        /// </summary>
        /// <returns>
        /// A reference to the newly created object.
        /// </returns>
        protected override Freezable CreateInstanceCore()
        {
            return (Freezable)Activator.CreateInstance(GetType());
        }

        /// <summary>
        /// Makes the instance a clone (deep copy) of the specified <see cref="Freezable"/>
        /// using base (non-animated) property values. 
        /// </summary>
        /// <param name="sourceFreezable">
        /// The object to clone.
        /// </param>
        protected sealed override void CloneCore(Freezable sourceFreezable)
        {
            base.CloneCore(sourceFreezable);
        }
        #endregion
    }

    /// <summary>
    /// Data resource binding extension class.
    /// </summary>
    public class DataResourceBindingExtension : MarkupExtension
    {
        #region Variables
        private object _targetObject;
        private object _targetProperty;
        private DataResource _dataResource;
        #endregion

        #region Constructor & destructor
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the data resource.
        /// </summary>
        /// <value>The data resource.</value>
        public DataResource DataResource
        {
            get
            {
                return _dataResource;
            }

            set
            {
                if (_dataResource != value)
                {
                    if (_dataResource != null)
                    {
                        _dataResource.Changed -= OnDataResourceChanged;
                    }

                    _dataResource = value;

                    if (_dataResource != null)
                    {
                        _dataResource.Changed += OnDataResourceChanged;
                    }
                }
            }
        }
        #endregion

        #region Methods
        /// <summary>
        /// When implemented in a derived class, returns an object that is set as the value of the target property for this markup extension.
        /// </summary>
        /// <param name="serviceProvider">Object that can provide services for the markup extension.</param>
        /// <returns>
        /// The object value to set on the property where the extension is applied.
        /// </returns>
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            IProvideValueTarget target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));

            _targetObject = target.TargetObject;
            _targetProperty = target.TargetProperty;

            // _targetProperty can be null when this is called in the Designer.
            Debug.Assert(_targetProperty != null || DesignerProperties.GetIsInDesignMode(new DependencyObject()));

            if (DataResource.BindingTarget == null && _targetProperty != null)
            {
                PropertyInfo propInfo = _targetProperty as PropertyInfo;
                if (propInfo != null)
                {
                    try
                    {
                        return Activator.CreateInstance(propInfo.PropertyType);
                    }
                    catch (MissingMethodException)
                    {
                        // there isn't a default constructor
                    }
                }

                DependencyProperty depProp = _targetProperty as DependencyProperty;
                if (depProp != null)
                {
                    DependencyObject depObj = (DependencyObject)_targetObject;
                    return depObj.GetValue(depProp);
                }
            }

            return DataResource.BindingTarget;
        }

        /// <summary>
        /// Called when the data resource has changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void OnDataResourceChanged(object sender, EventArgs e)
        {
            // Ensure that the bound object is updated when DataResource changes.
            DataResource dataResource = (DataResource)sender;
            DependencyProperty depProp = _targetProperty as DependencyProperty;

            if (depProp != null)
            {
                DependencyObject depObj = (DependencyObject)_targetObject;
                object value = Convert(dataResource.BindingTarget, depProp.PropertyType);
                depObj.SetValue(depProp, value);
            }
            else
            {
                PropertyInfo propInfo = _targetProperty as PropertyInfo;
                if (propInfo != null)
                {
                    object value = Convert(dataResource.BindingTarget, propInfo.PropertyType);
                    propInfo.SetValue(_targetObject, value, new object[0]);
                }
            }
        }

        /// <summary>
        /// Converts the specified object.
        /// </summary>
        /// <param name="obj">The object to convert.</param>
        /// <param name="toType">The type to convert the object to.</param>
        /// <returns>The converted object.</returns>
        private static object Convert(object obj, Type toType)
        {
            try
            {
                return System.Convert.ChangeType(obj, toType);
            }
            catch (InvalidCastException)
            {
                return obj;
            }
        }
        #endregion
    }
}

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
Software Developer
Netherlands Netherlands
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions