• Silverlight Chart and Google Financial Chart


    下面是我自己使用业余时间实现的silverlight chart area , 并组合两个chart area实现了google fiancial chart . 下面是截图和代码。仅供参考和学习。

    Helpers:

     public class AxisHelper
        { 
            public static void DrawAxis(ChartArea area, bool isXAxis)
            {
                GradeSetting gs = isXAxis ? area.XGradeSetting : area.YGradeSetting;
                var gls = area.Space.GetGradedLabels(gs, isXAxis);

                if (gls == null || gls.Count() == 0)
                    return;

                PathFigure pf = isXAxis ? area.xpf : area.ypf;

                pf.StartPoint = new Point(area.Space.StartPoint.X, area.Space.StartPoint.Y);
                pf.Segments.Clear();
                //start
                LineSegment sls = new LineSegment();
                sls.Point = new Point(area.Space.StartPoint.X, area.Space.StartPoint.Y);
                pf.Segments.Add(sls);
                //End point
                var els = new LineSegment();
                SPoint sp = isXAxis ? area.Space.XEndPoint : area.Space.YEndPoint;
                els.Point = new Point(sp.X, sp.Y);
                pf.Segments.Add(els);

                foreach (var gl in gls)
                {
                    Grid g = new Grid();
                    if (isXAxis)
                    {
                        g.RowDefinitions.Add(new RowDefinition { Height = new GridLength(0, GridUnitType.Auto) });
                        g.RowDefinitions.Add(new RowDefinition { Height = new GridLength(0, GridUnitType.Auto) });
                        g.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0, GridUnitType.Auto) });
                    }
                    else
                    {
                        g.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0, GridUnitType.Auto) });
                        g.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0, GridUnitType.Auto) });
                        g.RowDefinitions.Add(new RowDefinition { Height = new GridLength(0, GridUnitType.Auto) });
                    }
                    var cag = new ChartAreaGrid { Area = area, Margin = gl.Grade };
                    g.Tag = cag;
                    //grade
                    Rectangle r = new Rectangle
                    {
                        Width = gs.GradeWidth,
                        Height = gs.GradeHeigh,
                        Fill = new SolidColorBrush(Colors.Black),
                        HorizontalAlignment = HorizontalAlignment.Center
                    };
                    r.SetValue(isXAxis ? Grid.RowProperty : Grid.ColumnProperty, isXAxis ? 0 : 1);
                    g.Children.Add(r);
                    g.SizeChanged += new SizeChangedEventHandler(gy_SizeChanged);
                    //label
                    TextBlock txt = new TextBlock { Text = gl.Label, HorizontalAlignment = HorizontalAlignment.Center };
                    txt.SetValue(isXAxis ? Grid.RowProperty : Grid.ColumnProperty, isXAxis ? 1 : 0);
                    g.Children.Add(txt);
                    area.canvas.Children.Add(g);
                }
            }

            static void gy_SizeChanged(object sender, SizeChangedEventArgs e)
            {
                Grid g = sender as Grid;
                ChartAreaGrid cag = g.Tag as ChartAreaGrid;

                if (g.ColumnDefinitions.Count == 2)
                {
                    g.SetValue(Canvas.LeftProperty, cag.Area.Space.StartPoint.X - e.NewSize.Width + cag.Area.YGradeSetting.GradeWidth / 2);
                    g.SetValue(Canvas.TopProperty, cag.Margin - e.NewSize.Height / 2);
                }
                else
                {
                    g.SetValue(Canvas.LeftProperty, cag.Margin - cag.Area.XGradeSetting.GradeWidth / 2 - e.NewSize.Width / 2);
                    g.SetValue(Canvas.TopProperty, cag.Area.Space.StartPoint.Y - cag.Area.YGradeSetting.GradeHeigh / 2);
                }
            }

            class ChartAreaGrid
            {
                public ChartArea Area { get; set; }
                public double Margin { get; set; }
            }


            public static void DrawTopLeftAxis(ChartArea area)
            {

                PathFigure pf = area.trpf;

                pf.StartPoint = new Point(area.Space.YEndPoint.X , area.Space.YEndPoint .Y );
                pf.Segments.Clear();
                //start
                LineSegment sls = new LineSegment();
                sls.Point = new Point(area.Space.XEndPoint.X , area.Space.YEndPoint.Y );
                pf.Segments.Add(sls);
                //End point
                var els = new LineSegment();
                els.Point = new Point(area.Space.XEndPoint.X ,area .Space .XEndPoint .Y );
                pf.Segments.Add(els);
            }

          

        }

    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.Collections;
    using SLPocs.Helpers;
    using System.Linq;
    using System.Collections.Generic;
    using SLPocs.Entities;

    namespace SLPocs.Controls.Charts
    {
        public class SeriesHelper
        {

            public static void DrawLinealSries(ChartArea area)
            {
                foreach (var pth in area.Space.Pathes)
                {
                    DrawLinealSeries(area, pth);
                }
            }

            static void DrawLinealSeries(ChartArea area, SPath pth)
            {
                Path p = new Path();
                area.canvas.Children.Add(p);
                p.Stroke = new SolidColorBrush(pth.Color);
                p.StrokeThickness = 2;
                PathGeometry pg = new PathGeometry();
                p.Data = pg;
                PathFigure fig = new PathFigure();
                pg.Figures.Add(fig);
                fig.StartPoint = new Point(pth[0].X, pth[0].Y);
                foreach (var pnt in pth)
                {
                    var ls = new LineSegment();

                    ls.Point = new Point(pnt.X, pnt.Y);
                    fig.Segments.Add(ls);
                }
            }

        }
    }

    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.Collections.Generic;
    using System.Linq;

    namespace SLPocs.Controls.Charts
    {
        public class UerActionHelper
        {
            public static void AddResponseElement(ChartArea area, TraceType traceType)
            {
                switch (traceType)
                {
                    case  TraceType.CrossLine :
                        ShowCross(area);
                        break;
                    case TraceType.EllipseTrace :
                        ShowEllipses(area);
                        break;
                    case  TraceType.SelectRange :
                        ShowSelector(area);
                        break;
                }
            }

            public static void ShowCross(ChartArea area)
            {
                Line xline = new Line();
                xline.Tag = "xline";
                xline.X1 = area.Space.YEndPoint.X;
                xline.Y1 = area.Space.YEndPoint.Y;
                xline.X2 = area.Space.StartPoint.X;
                xline.Y2 = area.Space.StartPoint.Y;
                xline.Stroke = new SolidColorBrush(Colors.Green);
                xline.StrokeThickness = 2;
                area.canvas.Children.Add(xline);

                Line yline = new Line();
                yline.Tag = "yline";
                yline.X1 = area.Space.StartPoint.X;
                yline.Y1 = area.Space.StartPoint.Y;
                yline.X2 = area.Space.XEndPoint.X;
                yline.Y2 = area.Space.XEndPoint.Y; ;
                yline.Stroke = new SolidColorBrush(Colors.Green);
                yline.StrokeThickness = 2;
                area.canvas.Children.Add(yline);
            }

            private static void ShowEllipses(ChartArea area)
            {
                foreach (var sp in area.Space.Pathes)
                {
                    Ellipse eps = new Ellipse();
                    eps.Tag = sp.Key;
                    eps.Height = 6;
                    eps.Width = 6;
                    eps.Fill = new SolidColorBrush(sp.Color );
                    area.canvas.Children.Add(eps);
                    eps.SetValue(Canvas.LeftProperty, 0.0);
                    eps.SetValue(Canvas.TopProperty, 0.0);
                    eps.Visibility = Visibility.Collapsed;
                }
            }

            private static void ShowSelector(ChartArea area)
            {
                throw new NotImplementedException();
            }

            public  static void MoveResponseElements(ChartArea area, MouseEventArgs e)
            {
                switch (area.TraceType)
                {
                    case TraceType.CrossLine :
                        MoveCrossLine(area, e);
                        break;
                    case TraceType.EllipseTrace :
                        MoveEllipses(area, e);
                        break;
                }
            }


            static void MoveEllipses(ChartArea area, MouseEventArgs e)
            {
                double x = e.GetPosition(area.canvas).X;
                var ys = area.Space.GetYPiexes(x);
                var ells = area.canvas.Children.Where(a => a is Ellipse).Select(a=>a as Ellipse ).ToList();
                foreach (var pth in area.Space.Pathes)
                {
                    double? y = ys[pth.Key];
                    var ell = ells.First(a => a.Tag == pth.Key);
                    if (x < area.Space.StartPoint.X || x > area.Space.XEndPoint.X || !y.HasValue )
                        ell.Visibility = Visibility.Collapsed;
                    else
                    {
                        ell.Visibility = Visibility.Visible;
                        ell.SetValue(Canvas.TopProperty, y.Value-ell.Height/2);
                        ell.SetValue(Canvas.LeftProperty, x-ell.Width/2);
                    }
                       
                }
               
            }

            static void MoveCrossLine(ChartArea area, MouseEventArgs e)
            {
                var lines = area .canvas.Children.Where(x => x is Line);
                foreach (var line in lines)
                {
                    var l = line as Line;
                    if (l.Tag == "xline")
                    {
                        double x = e.GetPosition(area. canvas).X;
                        if (x > area.Space.XEndPoint.X)
                            x = area.Space.XEndPoint.X;
                        else if (x < area.Space.StartPoint.X)
                            x = area.Space.StartPoint.X;
                        l.X1 = x;
                        l.X2 = x;
                    }
                    else
                    {
                        double y = e.GetPosition(area.canvas).Y;
                        if (y > area.Space.StartPoint.Y)
                            y = area.Space.StartPoint.Y;
                        else if (y < area.Space.YEndPoint.Y)
                            y = area.Space.YEndPoint.Y;

                        l.Y1 = y;
                        l.Y2 = y;
                    }
                }
            }

        }
    }

    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.Windows.Data;

    namespace SLPocs.Controls
    {
            public class BindingHelper
            {
                public static void SetBindindFromSource(DependencyObject control, DependencyProperty property, object source, string path, BindingMode mode = BindingMode.OneWay, IValueConverter converter = null, UpdateSourceTrigger updateTrigger = UpdateSourceTrigger.Default)
                {
                    Binding binding = new Binding();
                    binding.Path = new PropertyPath(path);
                    binding.Mode = mode;
                    binding.Source = source;
                    binding.Converter = converter;

                    BindingOperations.SetBinding(control , property, binding);
                }
            }
     
    }

    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.Collections;
    using System.Collections.Generic;

    namespace SLPocs.Helpers
    {
        public class DynamicHelper
        {
            public static Func<object, object> GetSelector(Type T, string property)
            {
                var o = System.Linq.Expressions.Expression.Variable(typeof(object));
                var block = System.Linq.Expressions.Expression.Block(
                    System.Linq.Expressions.Expression.Convert(
                    System.Linq.Expressions.Expression.Property(System.Linq.Expressions.Expression.Convert(o, T), property), typeof(object))
                   );
                return System.Linq.Expressions.Expression.Lambda<Func<object, object>>(block, o).Compile();
            }

            public static object First(IEnumerable collection)
            {
                if (collection != null)
                {
                    foreach (var o in collection)
                        return o;
                }

                return null;               
            }

            public static IEnumerable<T> Select<T>(IEnumerable collection, Func<object, object> selector)
            {
                foreach (var o in collection)
                    yield return (T)selector(o);
            }

        }
    }

    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 SLPocs.Entities;

    namespace SLPocs.Helpers
    {
        public class MathHelper
        {
            public static double GetLineValue(double x, double x0, double y0, double x1, double y1)
            {
                return y0 + (y1 - y0) * (x - x0) / (x1 - x0);
            }

            public static double ConvertDatetimeToDouble(DateTime dt, DateTime from, TimeUnit tu)
            {
                if (tu == TimeUnit.Year)
                    return dt.Year - from.Year;
                if (tu == TimeUnit.Month)
                    return 12 * (dt.Year - from.Year) + dt.Month - from.Month;
                if (tu == TimeUnit.Day)
                    return (dt - from).TotalDays;
                if (tu == TimeUnit.Hour)
                    return (dt - from).TotalHours;
                if (tu == TimeUnit.Min)
                    return (dt - from).TotalMinutes;
                if (tu == TimeUnit.Second)
                    return (dt - from).TotalSeconds;
                if (tu == TimeUnit.MinSecond)
                    return (dt - from).TotalMilliseconds;
                return 0;
            }

            public static DateTime AddTime(double add, DateTime from, TimeUnit tu)
            {
                if (tu == TimeUnit.Year)
                    return from.AddYears((int)add);
                if (tu == TimeUnit.Month)
                    return from.AddMonths((int)add);
                if (tu == TimeUnit.Day)
                    return from.AddDays((int)add);
                if (tu == TimeUnit.Hour)
                    return from.AddHours(add);
                if (tu == TimeUnit.Min)
                    return from.AddMinutes(add);
                if (tu == TimeUnit.Second)
                    return from.AddSeconds(add);
                if (tu == TimeUnit.MinSecond)
                    return from.AddMilliseconds(add);
                return from;
            }

            public static void Shrink(FrameworkElement element, double xrate, double yrate)
            {
                element.Width = element.Width * xrate;
                element.Height = element.Height * yrate;
                double value = (double)element.GetValue(Canvas.LeftProperty);
                element.SetValue(Canvas.LeftProperty, value * xrate);
                value = (double)element.GetValue(Canvas.TopProperty);
                element.SetValue(Canvas.TopProperty, value * yrate);
            }

        }
    }

    XAML

    <UserControl xmlns:my="clr-namespace:SLPocs.Controls.Charts"  x:Class="SLPocs.Controls.Charts.ChartArea"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
        mc:Ignorable="d"
        d:DesignHeight="300" d:DesignWidth="400">

        <UserControl.Resources >
           
            <Grid x:Key="rangeSelector">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                    <ColumnDefinition Width="*"></ColumnDefinition>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                </Grid.ColumnDefinitions>

                <sdk:GridSplitter x:Name="leftSplitter"
                                  Grid.Column="1"
                                  VerticalAlignment="Stretch"
                                  Width="2"
                                  HorizontalAlignment="Left"
                                  Background="Gray"></sdk:GridSplitter>
                <sdk:GridSplitter x:Name="rightSplitter"
                                  Grid.Column="1"
                                  VerticalAlignment="Stretch"
                                  Width="2"
                                  HorizontalAlignment="Right"
                                  Background="Gray"></sdk:GridSplitter>
                <Border x:Name="selector_Bdr"
                        Grid.Column="1"
                        BorderThickness="0,2,0,2"
                        BorderBrush="Gray"
                        Background="Gray"
                        Opacity="0.1"
                        Margin="2" AllowDrop="True"  ></Border>
            </Grid>
           
        </UserControl.Resources>

            <Grid x:Name="LayoutRoot" MouseMove="LayoutRoot_MouseMove" Background="White" ShowGridLines="True">
               
            <Canvas x:Name="canvas" Background="Transparent">
            </Canvas>

            <my:RangeSelector x:Name="rangeSelector" />
               
               
                <Path x:Name="XAxis"
                  Stroke="Black"              
                  StrokeThickness="2">
                <Path.Data>
                    <PathGeometry>
                        <PathFigure x:Name="xpf">                       
                        </PathFigure>
                    </PathGeometry>
                </Path.Data>
            </Path>

            <Path x:Name="YAxis"
                  Stroke="Black"              
                  StrokeThickness="2">
                <Path.Data>
                    <PathGeometry>
                        <PathFigure x:Name="ypf">
                        </PathFigure>
                    </PathGeometry>
                </Path.Data>
            </Path>

            <Path x:Name="TopRightAxis"
                  Stroke="Black"              
                  StrokeThickness="2">
                <Path.Data>
                    <PathGeometry>
                        <PathFigure x:Name="trpf">
                        </PathFigure>
                    </PathGeometry>
                </Path.Data>
            </Path>

        </Grid>
    </UserControl>

    <UserControl x:Class="SLPocs.Controls.Charts.RangeSelector"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
        mc:Ignorable="d"
        Background="Transparent"
        HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
        d:DesignHeight="300" d:DesignWidth="400">
       
        <Grid x:Name="LayoutRoot" Background="Transparent" >
            <Canvas x:Name="selectorCanvas" Background="Transparent" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                <Border x:Name="leftSelectorGrid"  
                        BorderThickness="0"
                        Width="5"
                        Background="Gray"
                        MouseLeftButtonDown="leftSelectorGrid_MouseLeftButtonDown"
                        MouseLeftButtonUp="leftSelectorGrid_MouseLeftButtonUp"
                        MouseMove="leftSelectorGrid_MouseMove"></Border>
                <Border x:Name="selector"
                        BorderThickness="0,2,0,2"
                        Background="Gray"
                        Opacity="0.2"
                        MouseLeftButtonDown="selector_MouseLeftButtonDown"
                        MouseLeftButtonUp="selector_MouseLeftButtonUp"
                        MouseMove="selector_MouseMove"></Border>
                <Border x:Name="rightSelectorGrid" 
                        BorderThickness="0"
                        Width="5"
                        Background="Gray"  
                        MouseLeftButtonDown="rightSelectorGrid_MouseLeftButtonDown"
                        MouseLeftButtonUp="rightSelectorGrid_MouseLeftButtonUp"
                        MouseMove="rightSelectorGrid_MouseMove"></Border>
            </Canvas>
        </Grid>
    </UserControl>

    Behind code

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Collections;
    using SLPocs.Entities;
    using System.Windows.Data;

    namespace SLPocs.Controls.Charts
    {
        public partial class ChartArea : UserControl
        {
            public ChartArea()
            {
                InitializeComponent();
                this.SizeChanged += new SizeChangedEventHandler(ChartArea_SizeChanged);
                Space = new LinealSpace();
                Space.SetStartPoint(MarginX, MarginY+100);
                Space.SetLength(100, 100);
                rangeSelector.StartPercValue = 0.7;
                rangeSelector.EndPercValue = 0.9;

                rangeSelector.UpdateRangeAction = this.HandelSelectedItemsChanged;
            }


            public Size Size;
            protected override Size ArrangeOverride(Size finalSize)
            {
                Size = base.ArrangeOverride(finalSize);
                return Size;
            }

            bool initialized = false;
            void ChartArea_SizeChanged(object sender, SizeChangedEventArgs e)
            {
                UpdateUI();
                initialized = true;
            }

            public void UpdateUI()
            {
                Space.SetLength(this.Size.Width - 2 * MarginX, this.Size.Height - 2 * MarginY);
                Space.SetStartPoint(MarginX, this.Size.Height - MarginY);
                canvas.Children.Clear();

                SeriesHelper.DrawLinealSries(this);
                AxisHelper.DrawAxis(this, false);
                AxisHelper.DrawAxis(this, true);

                if (isRangeSelector)
                {
                    InitializeRangeSelectorSpace();
                    AxisHelper.DrawTopLeftAxis(this);
                }
                else
                    rangeSelector.Visibility = System.Windows.Visibility.Collapsed;
                  
                if(isTrace )
                    UerActionHelper.AddResponseElement(this, this.TraceType); ;
            }

            public LinealSpace Space = null;
            IEnumerable dataSource;
            public IEnumerable DataSource
            {
                get { return dataSource ; }
                set
                {
                   dataSource = value;
                   Space.FillData(dataSource, XPath, XGradeSetting .TimeUnit,IsRangeSeletor , YPaths);
                   if (initialized)
                       UpdateUI();
                }
            }

            public IEnumerable selectedItems;
            public IEnumerable SelectedItems { get { return selectedItems; } }
            public Action<IEnumerable> UpdateSelectedItems { get; set; }
            public void HandelSelectedItemsChanged(double start, double end)
            {
                if (isRangeSelector)
                {
                    double xlen= Space.XEndPoint .X -Space.StartPoint .X ;
                    double _start = xlen * start + Space.StartPoint.X, _end = xlen * end + Space.StartPoint.X;

                    selectedItems = Space.Pathes[0].Where(x => x.X >= _start && x.X < _end).Select(x => x.Item);
                    if (UpdateSelectedItems != null)
                        UpdateSelectedItems(selectedItems);
                }
            }

            public TraceType TraceType = TraceType.CrossLine;

            public string Caption { get; set; }

          


            #region XAxis Settings

            public double MarginX = 100;
            public string XPath = "X";

            public GradeSetting XGradeSetting = new GradeSetting {
                FixedPoints = 10,
                Format = "yyyy/MM/dd",
                GradeHeigh = 4,
                GradeWidth = 2,
                Internl = 100,
                GradeType = GradeType.FixedInternal,
                TimeUnit = TimeUnit.Day
            };

            #endregion

            #region YAxis Settings

            public string[] YPaths = new string[]{"Y1","Y2","Y3"};
            public double MarginY = 100;

            public GradeSetting YGradeSetting = new GradeSetting
            {
                FixedPoints = 10,
                Format = "0.00",
                GradeHeigh = 2,
                GradeWidth = 4,
                Internl = 10,
                GradeType = GradeType.FixedInternal,
                TimeUnit = TimeUnit.Day
            };   

            #endregion

            #region Selector

            bool isRangeSelector = true;
            public bool IsRangeSeletor { get { return isRangeSelector; } set { isRangeSelector = value; } }  
            void InitializeRangeSelectorSpace()
            {
                rangeSelector.Width = Space.XEndPoint.X - Space.StartPoint.X;
                rangeSelector.Height = Space.StartPoint.Y - Space.YEndPoint.Y;
                rangeSelector.Margin = new Thickness { Bottom = MarginX, Top = MarginX, Left = MarginY, Right = MarginY };
            }

            #endregion

            #region User Response

            bool isTrace = true;
            public bool IsTrace { get { return isTrace; } set { isTrace = value; } }

            private void LayoutRoot_MouseMove(object sender, MouseEventArgs e)
            {
                if (isTrace)
                    UerActionHelper.MoveResponseElements(this, e);          
                  
            }

            #endregion

        }

        public enum TraceType
        {
            CrossLine,
            EllipseTrace,
            SelectRange,
        }
    }

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using SLPocs.Helpers;

    namespace SLPocs.Controls.Charts
    {
        public partial class RangeSelector : UserControl
        {
            public RangeSelector()
            {
                InitializeComponent();
                this.SizeChanged += new SizeChangedEventHandler(RangeSelector_SizeChanged);
                leftSelectorGrid.Cursor = Cursors.SizeWE;
                selector.Cursor = Cursors.Hand;
                rightSelectorGrid.Cursor = Cursors.SizeWE;
            }

            public Action<double, double> UpdateRangeAction { get; set; }

            public double StartPercValue { get; set; }
            public double EndPercValue { get; set; }
            Size size;
            void RangeSelector_SizeChanged(object sender, SizeChangedEventArgs e)
            {
                size = e.NewSize;
                UpdateUI();
            }

            private void UpdateUI()
            {
                leftSelectorGrid.Height = size.Height;
                leftSelectorGrid.SetValue(Canvas.LeftProperty, size.Width * StartPercValue-leftSelectorGrid.Width);          
                selector.Height = size.Height;
                selector.Width = size.Width * (EndPercValue - StartPercValue);
                selector.SetValue(Canvas.LeftProperty, size.Width * StartPercValue);
                rightSelectorGrid.Height = size.Height;
                rightSelectorGrid.SetValue(Canvas.LeftProperty, size.Width * StartPercValue + selector.Width);
            } 

            double preLX;
            bool isLMouseCaptured;
            private void leftSelectorGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                SetPreX(sender, e, ref preLX,ref isLMouseCaptured);
            }

            private void leftSelectorGrid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
            {
                 HandleRelease(sender, e, ref preLX, ref isLMouseCaptured);
            }

            private void leftSelectorGrid_MouseMove(object sender, MouseEventArgs e)
            {
                HandleMove(sender, e, ref preLX, isLMouseCaptured,true );
               
            }

            double preSX;
            bool isSMouseCaptured;
            private void selector_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                SetPreX(sender ,e ,ref preSX ,ref isSMouseCaptured );
            }

            private void selector_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
            {
                 HandleRelease(sender, e, ref preSX, ref isSMouseCaptured);
            }

            private void selector_MouseMove(object sender, MouseEventArgs e)
            {
                HandleMove(sender, e, ref preSX, isSMouseCaptured,null );           
            }


            double preRX;
            bool isRMouseCaptured;
            private void rightSelectorGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                SetPreX(sender, e, ref preRX, ref isRMouseCaptured);
            }

            private void rightSelectorGrid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
            {
                HandleRelease(sender, e, ref preRX, ref isRMouseCaptured);
            }

            private void rightSelectorGrid_MouseMove(object sender, MouseEventArgs e)
            {
                HandleMove(sender, e, ref preRX, isRMouseCaptured,false);
            }
            void SetPreX(object sender, MouseEventArgs e, ref double px,ref bool isCaptured)
            {
                Border item = sender as Border;
                px = e.GetPosition(selectorCanvas).X;
                if (px < 0)
                    px = 0;
                else if (px > size.Width)
                    px = size.Width;
                item.CaptureMouse();
                isCaptured = true;
            }

            void HandleMove(object sender, MouseEventArgs e, ref double px, bool isCaptured,bool? isLeft)
            {
                Border item = sender as Border;
                if (isCaptured)
                {
                    double itemX = (double)item.GetValue(Canvas.LeftProperty);
                    double ex = e.GetPosition(selectorCanvas).X;
                    if (ex < 0)
                        ex = 0;
                    else if (ex > size.Width)
                        ex = size.Width;
                  
                    double deltaX =ex- px;
                    if (deltaX < 0 && deltaX + itemX < 0)
                        StartPercValue = 0;
                    else if (deltaX > 0 && itemX + item.Width + deltaX > size.Width)
                        EndPercValue = 1;
                    else if (isLeft.HasValue && isLeft.Value)
                        StartPercValue += deltaX / size.Width;
                    else if (isLeft.HasValue && !isLeft.Value)
                        EndPercValue += deltaX / size.Width;
                    else
                    {
                        StartPercValue += deltaX / size.Width;
                        EndPercValue += deltaX / size.Width;
                    }

                    UpdateUI();
                    // Update position global variables.
                    px = ex;
                }
            }

            void HandleRelease(object sender, MouseEventArgs e, ref double px, ref bool isCaptured)
            {
                Border item = sender as Border;
                isCaptured = false;
                item.ReleaseMouseCapture();
                if (UpdateRangeAction != null)
                    UpdateRangeAction(StartPercValue, EndPercValue);
            }

        }

        public struct RectangleArea
        {
            public double X1 { get; set; }
            public double Y1 { get; set; }
            public double X2 { get; set; }
            public double Y2 { get; set; }
            public bool IsRelative { get; set; }

            public void Shrink(double xrate, double yrate)
            {
                X1 *= xrate;
                X2 *= xrate;
                Y1 *= yrate;
                Y2 *= yrate;
            }
        }
    }

    How to use it

    <UserControl xmlns:my1="clr-namespace:SLPocs.Controls.Charts"  xmlns:syncfusion="clr-namespace:Syncfusion.Windows.Chart;assembly=Syncfusion.Chart.Silverlight"  xmlns:my="clr-namespace:SLPocs.Controls.Grids"  x:Class="SLPocs.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        d:DesignHeight="300" d:DesignWidth="400">

        <Grid x:Name="LayoutRoot" Background="White">
            <Grid.RowDefinitions >
                <RowDefinition Height="*"></RowDefinition>
                <RowDefinition Height="400"></RowDefinition>
            </Grid.RowDefinitions>
            <my1:ChartArea x:Name="detail"/>
            <my1:ChartArea x:Name="summary" Grid.Row="1" />
        </Grid>
    </UserControl>

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using SLPocs.Controls.Texts;
    using SLPocs.Controls.Arrows;
    using SLPocs.Controls.Charts;
    using SLPocs.Controls;
    using System.Collections.ObjectModel;
    using SLPocs.Entities;
    using System.Windows.Markup;
    using System.Collections;

    namespace SLPocs
    {
        public partial class MainPage : UserControl
        {
            public MainPage()
            {
                InitializeComponent();

                summary.DataSource = TestChartData.GetTestData();
                summary.IsTrace = false;
                summary.TraceType = TraceType.EllipseTrace;
                summary.XGradeSetting.GradeType = GradeType.FixedInternal;
                summary.UpdateSelectedItems = this.UpdateSelectedItems;

                detail.IsTrace = true;
                detail.IsRangeSeletor = false;
                detail.TraceType = TraceType.EllipseTrace;
                detail.XGradeSetting.GradeType = GradeType.FixedPoints ;

                         
            }

            void UpdateSelectedItems(IEnumerable data)
            {
                detail.DataSource = data;
            }
        }

        public class TestChartData
        {
            public double Y1 { get; set; }
            public double Y2 { get; set; }
            public double Y3 { get; set; }

            public DateTime X { get; set; }

            public static IEnumerable<TestChartData> GetTestData()
            {
                for (int i = 0; i < 2000; i++)
                    yield return new TestChartData
                    {
                        Y1 =100+ 50*Math.Sin(Math.PI *i/60),
                        Y2 = 100 + 50 * Math.Sin(Math.PI * i / 60+Math.PI /4),
                        Y3 = 100 + 50 * Math.Sin(Math.PI * i / 60+Math.PI/2),
                        X = DateTime.Now .AddDays (i ),
                    };
            }
        }
    }

  • 相关阅读:
    your account already has a valid ios distribution certificate
    uinavigation样式
    phonegap ios默认启动页
    git init出错
    ios assetlibrary
    uitableviewcell高度自适应笔记
    ios frame bounds applicationframe
    java学习笔记
    file not found while xcode archive
    c++回调
  • 原文地址:https://www.cnblogs.com/mjgb/p/2828505.html
Copyright © 2020-2023  润新知