<UserControl x:Class="CoolCharting.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" xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
xmlns:local="clr-namespace:CoolCharting">
<UserControl.Resources>
<local:CoolConverter x:Key="CoolConverter"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<toolkit:Chart x:Name="LineChart" BorderThickness="1" RenderTransformOrigin="1,0">
<toolkit:Chart.RenderTransform>
<ScaleTransform x:Name="LineChartScale"/>
</toolkit:Chart.RenderTransform>
<!-- Line series -->
<toolkit:LineSeries
ItemsSource="{Binding Converter={StaticResource CoolConverter}}"
IndependentValuePath="X"
DependentValuePath="Y"
TransitionDuration="0">
<toolkit:LineSeries.DataPointStyle>
<Style TargetType="toolkit:LineDataPoint">
<Setter Property="Background" Value="#ff3070ff"/>
<Setter Property="Width" Value="10"/>
<Setter Property="Height" Value="10"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="toolkit:LineDataPoint">
<Grid>
<Ellipse
Stroke="Black"
StrokeThickness="1"
Fill="{TemplateBinding Background}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</toolkit:LineSeries.DataPointStyle>
</toolkit:LineSeries>
<!-- Axes -->
<toolkit:Chart.Axes>
<toolkit:LinearAxis Orientation="Y" Minimum="0.5" Maximum="9.5" Interval="1" />
<toolkit:LinearAxis Orientation="X" Minimum="-0.01" Maximum="1.01"/>
</toolkit:Chart.Axes>
</toolkit:Chart>
<Button Content="刷新玄酷曲线" Click="BtnRefresh" Foreground="Black" HorizontalAlignment="Left" VerticalAlignment="Top"></Button>
</Grid>
</UserControl>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media.Animation;
namespace CoolCharting
{
public partial class MainPage : UserControl
{
#region 成员对象
private Random _rand = new Random();
#endregion
#region 构造函数
public MainPage()
{
InitializeComponent();
GenerateNewData();
}
#endregion
#region 方法
/// <summary>
/// 创建新的数据源
/// </summary>
private void GenerateNewData()
{
var count = 25;
var items = new Collection<Point>();
var last = 5.0;
for (var i = 0; i < count; i++)
{
//每一个新数据将产生在其上一数据附近
var min = Math.Max(1, last - 1);
var max = Math.Min(9, last + 1);
//而且必须在图形范围以内
var rand = last + ((_rand.NextDouble() * (max - min)) - (last - min));
//将数据加入集合
items.Add(new Point((double)i / (count - 1), rand));
last = rand;
}
//绑定集合到图形上
DataContext = items;
}
#endregion
#region 事件
/// <summary>
/// 点击刷新按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnRefresh(object sender, RoutedEventArgs e)
{
GenerateNewData();
}
#endregion
}
/// <summary>
/// 创建玄酷效果的关键转换类
/// </summary>
public class CoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// 空数据则退出
if (null == value)
{
return null;
}
// 检查输入类型,不符合要求则抛出异常
var originalPoints = value as ICollection<Point>;
if (null == originalPoints)
{
throw new NotImplementedException("Cool Converter only supports value type ICollection<T>.");
}
// 预备参数
var duration = TimeSpan.FromSeconds(0.5);
var delay = TimeSpan.FromSeconds(0.5);
var ease = new ElasticEase { Oscillations = 1 };
// 预备故事
var count = originalPoints.Count;
var CoolPoints = new List<CoolPoint>(count);
var storyboard = new Storyboard();
var propertyPath = new PropertyPath("Y");
var i = 0;
foreach (var originalItem in originalPoints)
{
//添加相对应的玄酷数据点
var CoolPoint = new CoolPoint { X = originalItem.X, Y = 0 };//关键
CoolPoints.Add(CoolPoint);
//创建一个动画效果
var animation = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(animation, CoolPoint);
Storyboard.SetTargetProperty(animation, propertyPath);
//配置初延时和玄酷行为
var thisDelay = TimeSpan.FromSeconds(delay.TotalSeconds * ((i + 1.0) / count));
animation.KeyFrames.Add(new LinearDoubleKeyFrame
{
KeyTime = thisDelay,
Value = 0
});
animation.KeyFrames.Add(new EasingDoubleKeyFrame
{
KeyTime = thisDelay + duration,
Value = originalItem.Y,
EasingFunction = ease
});
//添加动画效果到故事板
animation.Duration = thisDelay + duration;
storyboard.Children.Add(animation);
i++;
}
//播放玄酷曲线效果
storyboard.Begin();
return CoolPoints;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public class CoolPoint : DependencyObject, INotifyPropertyChanged
{
public static readonly DependencyProperty YProperty = DependencyProperty.Register("Y", typeof(double), typeof(CoolPoint), new PropertyMetadata(YPropertyChanged));
private static PropertyChangedEventArgs _yPropertyChangedEventArgs = new PropertyChangedEventArgs("Y");
public event PropertyChangedEventHandler PropertyChanged;
public double X { get; set; }
public double Y
{
get { return (double)GetValue(YProperty); }
set { SetValue(YProperty, value); }
}
private static void YPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
var CoolPoint = (CoolPoint)o;
var handler = CoolPoint.PropertyChanged;
if (null != handler)
{
handler.Invoke(CoolPoint, _yPropertyChangedEventArgs);
}
}
}
}
}