Silverlight Toolkit提供了绘制柱状图(Column,Bar),饼图(Pie),折线图(Line), 散点图(Scatter)等控件。我们可以很方便的将已有的数据源绑定到相应图形控件上,设置好相应的X,Y轴显示样式和数据字段之后就大功告成了,同时其还支持图形的定时加载刷新,图形的动态加载动画效果。今天就先以柱状图为例,简要的总结一下如何使用该控件来显示我们的数据。

    首先,我们需要创建一个Silverlight项目,命名为:DataVisualization。
   
    然后我们使用WCF方式发布数据源信息,这里我们创建一个"Silverlight功能的WCF",并将其命名为:

      DataService.svc

使用Silverlight Toolkit绘制图表(上)--柱状图_13753

    接着将下面的代码拷贝到该类文件中:
  1. public class EmployeeInfo
  2. {
  3.     public int EmployeeID { set; get; }
  4.     public string EmployeeName { set; get; }
  5.     public int Salary { set; get; }
  6.     public int[] Cost { get; set; }
  7.     public string City { set; get; }

  8.  
  9. [ServiceContract(Namespace = "")]
  10. [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
  11. public class DataService
  12. {
  13.     [OperationContract]
  14.     public List<EmployeeInfo> GetEmployeeList()
  15.     {
  16.         List<EmployeeInfo> employeeList = new List<EmployeeInfo>();
  17.         employeeList.Add(new EmployeeInfo { EmployeeID = 1, EmployeeName = "张三", Salary = 1000, City = "合肥" });
  18.         employeeList.Add(new EmployeeInfo { EmployeeID = 2, EmployeeName = "李四", Salary = 1500, City = "天津" });
  19.         employeeList.Add(new EmployeeInfo { EmployeeID = 3, EmployeeName = "王五", Salary = 2000, City = "上海" });
  20.         employeeList.Add(new EmployeeInfo { EmployeeID = 4, EmployeeName = "赵六", Salary = -800, City = "北京" });
  21.         employeeList.Add(new EmployeeInfo { EmployeeID = 5, EmployeeName = "尤七", Salary = 2100, City = "武汉" });
  22.         employeeList.Add(new EmployeeInfo { EmployeeID = 6, EmployeeName = "马八", Salary = 2300, City = "海口" });
  23.         return employeeList;
  24.     }
  25. }
复制代码
这里数据源我们就创建完成了,它将会返回6个雇员信息。
 
    下面我们往该Silverlight应用的Xaml文件上拖(或手工声明)一个Chart控件,如下: 
   
<charting:Chart Title="员工薪水" x:Name="EmployeeChart"></charting:Chart>
   
    我们看到在该控件上我们指定了Title信息,该信息会显示在图表的最上方。
 
  下面开始编写CS代码。
 
    1.首先我们向该Silverlight应用中添加对刚才声明的WCF的引用。
 
    2.使用WCF生成的客户端类来获取相应的数据源,代码如下:
  1. void LoadWcfData()
  2. {
  3.     dataServiceClient.GetEmployeeListCompleted += new EventHandler<GetEmployeeListCompletedEventArgs>(dataServiceClient_GetEmployeeListCompleted);
  4.     dataServiceClient.GetEmployeeListAsync();
  5. }
复制代码
3.将WCF返回的数据源信息绑定到相应的图形控件上,并初始化该控件的相应信息,如下:
  1. void dataServiceClient_GetEmployeeListCompleted(object sender, GetEmployeeListCompletedEventArgs e)
  2. {
  3.     ObservableCollection<EmployeeInfo> employeeList = e.Result;

  4.     Action<Chart> chartModifier = (chart) =>
  5.     {
  6.         Axis dateAxis = new Axis { Orientation = AxisOrientation.Horizontal, Title = "雇员名称", FontStyle = FontStyles.Normal, FontSize = 12f, ShowGridLines = true};
  7.         EmployeeChart.Axes.Add(dateAxis);
  8.         Axis valueAxis = new Axis { Orientation = AxisOrientation.Vertical, Title = "薪水", Minimum = -1000, Maximum = 3000, ShowGridLines = true};
  9.         EmployeeChart.Axes.Add(valueAxis);
  10.     };
  11.     chartModifier(EmployeeChart);

  12.     ColumnSeries series = new ColumnSeries();
  13.     series.ItemsSource = employeeList;
  14.     series.IndependentValueBinding = new System.Windows.Data.Binding("EmployeeName");
  15.     series.DependentValueBinding = new System.Windows.Data.Binding("Salary");
  16.     series.Title = "薪水";
  17.     EmployeeChart.Series.Add(series);
  18. }
复制代码
在上面的代码中我们创建了Axis对象用以将X,Y轴的描述信息绑定到指定的图形控件上,然后将我们的指定数据源绑定到该图形控件的ItemsSource属性上,最后再绑定两个座标轴要显示的相应数据:

    X轴:  series.IndependentValueBinding = new System.Windows.Data.Binding("EmployeeName");
   
    Y轴:  series.DependentValueBinding = new System.Windows.Data.Binding("Salary");
       
    下面我们来看一下最终的显示效果,如下图所示:
   
    使用Silverlight Toolkit绘制图表(上)--柱状图_13754
 
    大家看到,在Y轴上我们既显示了正轴也显示了负轴,这就是通过Minimum = -1000, Maximum = 3000这一行设置实现的。 
   
    还不错了,到这里我们只是简要的领略了一个图形控件的基本功能。接着我们再了解一下它还有那些更高级的使用技巧。

    首先是图形的定时加载刷新,要实现这个演示,我们需要一个实时变化的数据源,以便当我们定时刷新控件时能显示不同的数据信息。所以我们要在WCF中创建一个这样的数据源:
  1. [OperationContract]
  2. public List<EmployeeInfo> GetEmployeeDynamicList()
  3. {
  4.     Random random = new Random();
  5.     List<EmployeeInfo> employeeList = new List<EmployeeInfo>();
  6.     employeeList.Add(new EmployeeInfo { EmployeeID = 1, EmployeeName = "张三", Salary = random.Next(500, 3000), City = "合肥" });
  7.     employeeList.Add(new EmployeeInfo { EmployeeID = 2, EmployeeName = "李四", Salary = random.Next(500, 3000), City = "天津" });
  8.     employeeList.Add(new EmployeeInfo { EmployeeID = 3, EmployeeName = "王五", Salary = random.Next(500, 3000), City = "上海" });
  9.     employeeList.Add(new EmployeeInfo { EmployeeID = 4, EmployeeName = "赵六", Salary = random.Next(500, 3000), City = "北京" });
  10.     employeeList.Add(new EmployeeInfo { EmployeeID = 5, EmployeeName = "尤七", Salary = random.Next(500, 3000), City = "武汉" });
  11.     employeeList.Add(new EmployeeInfo { EmployeeID = 6, EmployeeName = "马八", Salary = random.Next(500, 3000), City = "海口" });
  12.     return employeeList;
  13. }
复制代码
大家看到,这里使用了Random来模拟一个动态数据源信息,其生成的随机数介于500-3000之间,那么接下来,我们再Silverlight的XAML上创建这样一个Chart对象,用以显示该动态数据源信息,如下:   

<charting:Chart Title="动态员工薪水" x:Name="DynamicEmployeeChart" />
   
    接着就是相应的CS代码了,这里为了方便起见,这里直接使用DispatcherTimer来定时(3秒)获取相应的数据源信息,如下:
  1. void LoadDynamicData()
  2. {
  3.     System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
  4.     dispatcherTimer.Interval = TimeSpan.FromSeconds(3);
  5.     dispatcherTimer.Tick += delegate
  6.     {             
  7.         dataServiceClient.GetEmployeeDynamicListCompleted += new EventHandler<GetEmployeeDynamicListCompletedEventArgs>(dataServiceClient_GetEmployeeDynamicListCompleted);
  8.         dataServiceClient.GetEmployeeDynamicListAsync();
  9.     };
  10.     dispatcherTimer.Start();
  11. }
复制代码
接着就是初始化相应的图形控件并绑定相应的数据源了,代码与上面的CS代码相似,如下:
  1. void dataServiceClient_GetEmployeeDynamicListCompleted(object sender, GetEmployeeDynamicListCompletedEventArgs e)
  2. {
  3.     ObservableCollection<EmployeeInfo> employeeList = e.Result;
  4.     DynamicEmployeeChart.Axes.Clear();
  5.     DynamicEmployeeChart.Series.Clear();
  6.     Action<Chart> chartModifier = (chart) =>
  7.     {
  8.         Axis dateAxis = new Axis { Orientation = AxisOrientation.Horizontal, Title = "雇员名称", FontStyle = FontStyles.Normal, FontSize = 12f, ShowGridLines = true };
  9.         DynamicEmployeeChart.Axes.Add(dateAxis);
  10.         Axis valueAxis = new Axis { Orientation = AxisOrientation.Vertical, Title = "薪水", Minimum = 0, Maximum = 3000, ShowGridLines = true };
  11.         DynamicEmployeeChart.Axes.Add(valueAxis);
  12.     };
  13.     chartModifier(DynamicEmployeeChart);

  14.     ColumnSeries series = new ColumnSeries();
  15.     series.ItemsSource = employeeList;
  16.     series.IndependentValueBinding = new System.Windows.Data.Binding("EmployeeName");
  17.     series.DependentValueBinding = new System.Windows.Data.Binding("Salary");
  18.     series.Title = "薪水";
  19.     DynamicEmployeeChart.Series.Add(series);
  20. }
复制代码
好了,这里我们看一下最终的运行效果,首先是刚启动运行时的截图:
   
  使用Silverlight Toolkit绘制图表(上)--柱状图_13755
   
    然后是三秒之后的运行截图:
   
    使用Silverlight Toolkit绘制图表(上)--柱状图_13756
   
    到这里还不算完,因为该控件还支持数据的分组显示,比如说如果我们的数据中有数组类型的字段信息,该控件是以数组为单位(数组长度就是图表的列信息)。这个有些难以理解,下面就以一个示例来加以说明。

首先,我们要创建一个具有数组类型字段的数据源,如下:
  1. [OperationContract]
  2. public List<EmployeeInfo> GetMultiSeriesEmployeeList()
  3. {
  4.     List<EmployeeInfo> employeeList = new List<EmployeeInfo>();
  5.     employeeList.Add(new EmployeeInfo { EmployeeID = 1, EmployeeName = "张三", Salary = 1000, Cost = new int[] { 100, 160 } });
  6.     employeeList.Add(new EmployeeInfo { EmployeeID = 2, EmployeeName = "李四", Salary = 1500, Cost = new int[] { 260, 200 } });
  7.     employeeList.Add(new EmployeeInfo { EmployeeID = 3, EmployeeName = "王五", Salary = 2000, Cost = new int[] { 360, 330 } });
  8.     employeeList.Add(new EmployeeInfo { EmployeeID = 4, EmployeeName = "赵六", Salary = 800, Cost = new int[] { 160, 430 } });
  9.     employeeList.Add(new EmployeeInfo { EmployeeID = 5, EmployeeName = "尤七", Salary = 2100, Cost = new int[] { 560, 530 } });
  10.     employeeList.Add(new EmployeeInfo { EmployeeID = 6, EmployeeName = "马八", Salary = 2300, Cost = new int[] { 660, 600 } });
  11.     return employeeList;
  12. }
复制代码
大家看到了,在该数据源中的Cost属性即是数据类型字段,该字段记录了雇员的交费信息:第一项为“住房公积金”,第二项为“个人养老金”。

    下面我们就来看一下该如何绑定这类数据源信息。
   
    首先在XAML中创建该图表控件,如下:
   
<charting:Chart Title="MultiSeries" x:Name="MultiSeries" MouseLeftButt/>

    大家看到这里我们还绑定了鼠标单击事件,该事件主要用于稍后演示图表的动态效果,这里先行略过:)
   
    接着就是我们的CS代码了,首先是获取数据源:
  1. void LoadMultiSeries()
  2. {
  3.     dataServiceClient.GetMultiSeriesEmployeeListCompleted += new EventHandler<GetMultiSeriesEmployeeListCompletedEventArgs>(dataServiceClient_GetMultiSeriesEmployeeListCompleted);
  4.     dataServiceClient.GetMultiSeriesEmployeeListAsync();
  5. }
复制代码
然后是相应的控件初始化和数据绑定代码:
  1. void dataServiceClient_GetMultiSeriesEmployeeListCompleted(object sender, GetMultiSeriesEmployeeListCompletedEventArgs e)
  2. {
  3.     ObservableCollection<EmployeeInfo> employeeList = e.Result;
  4.  
  5.     Action<Chart> chartModifier = (chart) =>
  6.     {
  7.         Axis dateAxis = new Axis { Orientation = AxisOrientation.Horizontal, Title = "注 1:住房公积金  2:个人养老金", FontStyle = FontStyles.Normal, FontSize = 14f, ShowGridLines = true };
  8.         MultiSeries.Axes.Add(dateAxis);
  9.      
  10.         Axis valueAxis = new Axis { Orientation = AxisOrientation.Vertical, Title = "税金", Minimum = 0, Maximum = 800, ShowGridLines = true };
  11.         MultiSeries.Axes.Add(valueAxis);
  12.     };
  13.     chartModifier(MultiSeries);

  14.     foreach (EmployeeInfo itemsSource in employeeList)
  15.     {
  16.         ColumnSeries series = new ColumnSeries();
  17.         series.ItemsSource = itemsSource.Cost;
  18.         series.DependentValueBinding = null;
  19.         series.IndependentValueBinding = null;
  20.         series.Title = itemsSource.EmployeeName + " ID:" + itemsSource.EmployeeID;
  21.         series.AnimationSequence = AnimationSequence.FirstToLast;
  22.         MultiSeries.Series.Add(series);
  23.     }       
  24. }
复制代码
这里我们看到在控件的数据源绑定上与前两个DEMO存在一定的差异。因为每个雇员的交费字段本身就是一个数组(整形),所以这里将该交费字段直接绑定到了ColumnSeries的ItemsSource属性上。同时将ColumnSeries 的属性 DependentValueBinding,IndependentValueBinding分别设置为null。这里给该ColumnSeries的动态显示效果设置成了AnimationSequence.FirstToLast。下面我们会看到显示效果,而相应的鼠标单击事件代码摘自TOOKIT的
代码示例包,这里就不多加解释了。下面是相应的显示效果:

    使用Silverlight Toolkit绘制图表(上)--柱状图_13757
   
    当我们在图表上单击鼠标时,显示效果如下:
   
使用Silverlight Toolkit绘制图表(上)--柱状图_13759 使用Silverlight Toolkit绘制图表(上)--柱状图_13758
   
    等图表全被隐去时,这时我们再单击鼠标,图表会依次再显示出来。
         
    除了数据动态加载,Chart还支持数据的静态绑定,如下面的XAML代码即是初始并绑定一个已存在的数据源:
  1. <charting:Chart Title="Xaml绑定" x:Name="FunctionSeriesSample" MouseLeftButtonDown="OnMouseLeftButtonDown">
  2.     <charting:Chart.Series>
  3.         <charting:ColumnSeries
  4.             Title="人口" AnimationSequence="FirstToLast"
  5.             ItemsSource="{Binding PugetSound, Source={StaticResource City}}"
  6.             IndependentValueBinding="{Binding Name}"
  7.             DependentValueBinding="{Binding Population}"/> 
  8.     </charting:Chart.Series>
  9.     <charting:Chart.Axes>
  10.         <charting:Axis AxisType="Category" Title="城市" Orientation="Horizontal" FontStyle="Italic"/>
  11.         <charting:Axis AxisType="Linear" Title="人口" Orientation="Vertical" Minimum="0" Maximum="600000" Interval="100000" ShowGridLines="True"  FontStyle="Italic"/>
  12.     </charting:Chart.Axes>
  13. </charting:Chart>
复制代码
而数据源是在程序中直接写死的,如下:
  1. /**//// <summary>
  2. /// City business object used for charting samples.
  3. /// </summary>
  4. public class City
  5. {
  6.     /**//// <summary>
  7.     /// Gets or sets the name of the city.
  8.     /// </summary>
  9.     public int ID { get; set; }

  10.     /**//// <summary>
  11.     /// Gets or sets the name of the city.
  12.     /// </summary>
  13.     public string Name { get; set; }

  14.     /**//// <summary>
  15.     /// Gets or sets the population of the city.
  16.     /// </summary>
  17.     public int Population { get; set; }

  18.     /**//// <summary>
  19.     /// Initializes a new instance of the City class.
  20.     /// </summary>
  21.     public City()
  22.     {
  23.     }

  24.     /**//// <summary>
  25.     /// Returns a string that represents the current object.
  26.     /// </summary>
  27.     /// <returns>A string that represents the current object.</returns>
  28.     public override string ToString()
  29.     {
  30.         return Name;
  31.     }

  32.     /**//// <summary>
  33.     /// Gets a collection of cities in the Puget Sound area.
  34.     /// </summary>
  35.     public static ObjectCollection PugetSound
  36.     {
  37.         get
  38.         {
  39.             ObjectCollection pugetSound = new ObjectCollection();
  40.             pugetSound.Add(new City { Name = "张庄", Population = 312344, ID = 1 });
  41.             pugetSound.Add(new City { Name = "李庄", Population = 411212, ID = 2 });
  42.             pugetSound.Add(new City { Name = "赵庄", Population = 261391, ID = 3 });
  43.             pugetSound.Add(new City { Name = "马家河子", Population = 530022, ID = 4 });
  44.             return pugetSound;
  45.         }
  46.     }
  47. }
复制代码
到这里,有关柱状图的主要功能介绍的差不多了,但如果开发过相应图表功能的朋友会发现,之前的DEMO显示的都是垂直的柱状图,但很多的网站上显示的都是水平方向的柱状图,比如说投票功能等,其实Chart实现这个功能非常简要,只要在我们原有的CS代码基础上做很少的改动即可实现,这里以上面的第
一个DEMO为例,看一下如何进行改造:

    下面是其dataServiceClient_GetEmployeeListCompleted方法的改造后的代码:
  1. void dataServiceClient_GetEmployeeListCompleted(object sender, GetEmployeeListCompletedEventArgs e)
  2. {
  3.     ObservableCollection<EmployeeInfo> employeeList = e.Result;

  4.     Action<Chart> chartModifier = (chart) =>
  5.     {
  6.         Axis dateAxis = new Axis { Orientation = AxisOrientation.Vertical, Title = "雇员名称", FontStyle = FontStyles.Normal, FontSize = 12f, ShowGridLines = true };
  7.         EmployeeChart.Axes.Add(dateAxis);
  8.         Axis valueAxis = new Axis { Orientation = AxisOrientation.Horizontal, Title = "薪水", Minimum = -1000, Maximum = 3000, ShowGridLines = true};
  9.         EmployeeChart.Axes.Add(valueAxis);
  10.     };
  11.     chartModifier(EmployeeChart);

  12.     BarSeries series = new BarSeries();
  13.     series.ItemsSource = employeeList;
  14.     series.IndependentValueBinding = new System.Windows.Data.Binding("EmployeeName");
  15.     series.DependentValueBinding = new System.Windows.Data.Binding("Salary");
  16.     EmployeeChart.Series.Add(series);
  17. }
复制代码
在这里,我们看到了之前所设置的X,Y轴在AxisOrientation属性上被做了交换设置。而接着的ColumnSeries对象也被替换成了BarSeries。这样我们就完成了相应的改造(更多信息参见DEMO源码BarSample)。

      其它的DEMO只要参照一下上面所说的替换方式替换一下即可,最终我们看一个显示效果,如下图所示:
   
使用Silverlight Toolkit绘制图表(上)--柱状图_13760
   
    好了,今天的内容就先到这里了。

源码下载,请点击这里:
附件: 亲,您没有权限下载或查看附件喔:-) 试试登录注册吧!
TOP

回复 1# cobra 的帖子

如何是否可以把源代码共享一下啊?
TOP

楼主太强了,学习。
TOP

楼主太强了,学习。
TOP

深情顶帖,楼主加油!
TOP

深情顶帖,楼主加油!
TOP

深情顶帖,楼主加油!
TOP

深情顶帖,楼主加油!
TOP

深情顶帖,楼主加油!
TOP

深情顶帖,楼主加油!
TOP