Click here to Skip to main content
15,895,746 members
Articles / Mobile Apps / Windows Phone 7

XAMLFinance – A Cross-platform WPF, Silverlight & WP7 Application

Rate me:
Please Sign up or sign in to vote.
4.94/5 (99 votes)
21 Sep 2011CPOL27 min read 217.8K   9.9K   251  
This article describes the development of XAML Finance, a cross-platform application which works on the desktop, using Windows Presentation Foundation (WPF), on the web, using Silverlight and on Windows Phone 7 (WP7).
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.

using System.Globalization;
using System.Windows.Data;

namespace System.Windows.Controls.DataVisualization
{
    /// <summary>
    /// Abstract base class for Interpolator converters.
    /// </summary>
    /// <remarks>
    /// <para>
    /// An Interpolator is used to project a value from a source range 
    /// [ActualDataMinimum, ActualDataMaximum] to a target range [From, To]. 
    /// The source range can be specified directly by setting the DataMinimum 
    /// and/or DataMaximum properties, or indirectly by setting DataRangeBinding.
    /// When the DataRangeBinding property is set,the TreeMap will evaluate the 
    /// binding for the entire tree, calculating the minimum and maximum values 
    /// automatically. The custom target range and the actual interpolation 
    /// logic is defined by sub-classes of this abstract class.
    /// </para>
    /// </remarks>
    /// <QualityBand>Experimental</QualityBand>
    public abstract class Interpolator : FrameworkElement
    {
        /// <summary>
        /// Holds a helper object used to extract values using a property path.
        /// </summary>
        private BindingExtractor _helper;

        /// <summary>
        /// Gets or sets a value telling to which tree nodes the interpolation 
        /// should be applied to. LeafNodesOnly by default.
        /// </summary>
        public InterpolationMode InterpolationMode { get; set; }

        /// <summary>
        /// Gets or sets a value representing the x:Name of the element to which
        /// the interpolated value will be applied.
        /// </summary>
        public string TargetName { get; set; }

        /// <summary>
        /// Gets or sets a value representing the path to a property which will 
        /// receive the interpolated value.
        /// </summary>
        public string TargetProperty { get; set; }

        #region public double DataMinimum
        /// <summary>
        /// Gets or sets a value representing the fixed minimum value across the 
        /// entire set. If the value is not set directly or is NaN, the 
        /// ActualDataMaximum will be calculated automatically from the data set 
        /// by using the DataRangeBinding property.
        /// </summary>
        public double DataMinimum
        {
            get { return (double)GetValue(DataMinimumProperty); }
            set { SetValue(DataMinimumProperty, value); }
        }

        /// <summary>
        /// Identifies the DataMinimum dependency property.
        /// </summary>
        public static readonly DependencyProperty DataMinimumProperty =
            DependencyProperty.Register(
                "DataMinimum",
                typeof(double),
                typeof(Interpolator),
                new PropertyMetadata(double.NaN));
        #endregion public double DataMinimum

        #region public double DataMaximum
        /// <summary>
        /// Gets or sets a value representing the fixed maximum value across the 
        /// entire set. If the value is not set directly or is NaN, the 
        /// ActualDataMinimum will be calculated automatically from the data set 
        /// by using the DataRangeBinding property.
        /// </summary>
        public double DataMaximum
        {
            get { return (double)GetValue(DataMaximumProperty); }
            set { SetValue(DataMaximumProperty, value); }
        }

        /// <summary>
        /// Identifies the DataMaximum dependency property.
        /// </summary>
        public static readonly DependencyProperty DataMaximumProperty =
            DependencyProperty.Register(
                "DataMaximum",
                typeof(double),
                typeof(Interpolator),
                new PropertyMetadata(double.NaN));
        #endregion public double DataMaximum

        /// <summary>
        /// This fields contains the automatically calculated maximal value in 
        /// the dataset.
        /// </summary>
        private double _actualDataMaximum;

        /// <summary>
        /// Gets the value representing the maximal value in the data set. It is
        /// automatically from the data set by using the DataRangeBinding 
        /// property if DataMaximum is not set. If it is set, DataMaximum is 
        /// returned.
        /// </summary>
        public double ActualDataMaximum
        {
            get
            {
                if (Double.IsNaN(DataMaximum))
                {
                    return _actualDataMaximum;
                }
                else
                {
                    return DataMaximum;
                }
            }

            internal set
            {
                _actualDataMaximum = value;
            }
        }

        /// <summary>
        /// This fields contains the automatically calculated minimal value in 
        /// the dataset.
        /// </summary>
        private double _actualDataMinimum;

        /// <summary>
        /// Gets the value representing the minimal value in the data set. It is
        /// automatically from the data set by using the DataRangeBinding 
        /// property if DataMinimum is not set. If it is set, DataMinimum is 
        /// returned.
        /// </summary>
        public double ActualDataMinimum
        {
            get
            {
                if (Double.IsNaN(DataMinimum))
                {
                    return _actualDataMinimum;
                }
                else
                {
                    return DataMinimum;
                }
            }

            internal set
            {
                _actualDataMinimum = value;
            }
        }

        /// <summary>
        /// Gets or sets a binding to a property which will be examined to retrieve the minimum and maximum range 
        /// values across the entire data set. If this value is null then the DataMinimum and DataMaximum values
        /// need be set manually.
        /// </summary>
        public Binding DataRangeBinding { get; set; }

        /// <summary>
        /// Initializes a new instance of the Interpolator class.
        /// </summary>
        protected Interpolator()
        {
            InterpolationMode = InterpolationMode.LeafNodesOnly;
            ActualDataMinimum = double.PositiveInfinity;
            ActualDataMaximum = double.NegativeInfinity;
            _helper = new BindingExtractor();
        }

        /// <summary>
        /// If the DataRangeBinding property is set then this method updates the minimum/maximum range
        /// of this object by including the value passed in.
        /// </summary>
        /// <param name="data">Object to extract the value from (the Source of the DataRangeBinding).</param>
        internal virtual void IncludeInRange(object data)
        {
            if (DataRangeBinding != null)
            {
                if (!Double.IsNaN(DataMinimum) && !Double.IsNaN(DataMaximum))
                {
                    return;
                }

                IConvertible input = _helper.RetrieveProperty(data, DataRangeBinding) as IConvertible;
                if (input == null)
                {
                    throw new ArgumentException("Interpolator_IncludeInRange_DataRangeBindingNotIConvertible");
                }

                double value = input.ToDouble(CultureInfo.InvariantCulture);
                if (Double.IsNaN(DataMinimum) && value < ActualDataMinimum)
                {
                    ActualDataMinimum = value;
                }

                if (Double.IsNaN(DataMaximum) && value > ActualDataMaximum)
                {
                    ActualDataMaximum = value;
                }
            }
        }

        /// <summary>
        /// Called to interpolate the value of the given object between the DataMinimum and DataMaximum
        /// extremes, and to project it in a specific [From, To] range defined. The target range (and
        /// therefore the implementation of this method) is defined in a specific sub-class.
        /// </summary>
        /// <param name="value">Value to interpolate.</param>
        /// <returns>An interpolated value.</returns>
        public abstract object Interpolate(double value);
    }
}

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
Architect Scott Logic
United Kingdom United Kingdom
I am CTO at ShinobiControls, a team of iOS developers who are carefully crafting iOS charts, grids and controls for making your applications awesome.

I am a Technical Architect for Visiblox which have developed the world's fastest WPF / Silverlight and WP7 charts.

I am also a Technical Evangelist at Scott Logic, a provider of bespoke financial software and consultancy for the retail and investment banking, stockbroking, asset management and hedge fund communities.

Visit my blog - Colin Eberhardt's Adventures in .NET.

Follow me on Twitter - @ColinEberhardt

-

Comments and Discussions